cluxion-agentplugin-preprocessing 0.3.21__tar.gz → 0.3.23__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 (102) hide show
  1. {cluxion_agentplugin_preprocessing-0.3.21 → cluxion_agentplugin_preprocessing-0.3.23}/PKG-INFO +1 -1
  2. {cluxion_agentplugin_preprocessing-0.3.21 → cluxion_agentplugin_preprocessing-0.3.23}/pyproject.toml +1 -1
  3. cluxion_agentplugin_preprocessing-0.3.23/rust/cluxion_queue/uv.lock +8 -0
  4. {cluxion_agentplugin_preprocessing-0.3.21 → cluxion_agentplugin_preprocessing-0.3.23}/src/cluxion_agentplugin_preprocessing/plugin.py +27 -1
  5. {cluxion_agentplugin_preprocessing-0.3.21 → cluxion_agentplugin_preprocessing-0.3.23}/src/cluxion_agentplugin_preprocessing/plugin.yaml +2 -1
  6. {cluxion_agentplugin_preprocessing-0.3.21 → cluxion_agentplugin_preprocessing-0.3.23}/src/cluxion_agentplugin_preprocessing/runner.py +14 -0
  7. {cluxion_agentplugin_preprocessing-0.3.21 → cluxion_agentplugin_preprocessing-0.3.23}/src/cluxion_agentplugin_preprocessing/schemas.py +52 -0
  8. cluxion_agentplugin_preprocessing-0.3.23/src/cluxion_agentplugin_preprocessing/slash_commands.py +121 -0
  9. {cluxion_agentplugin_preprocessing-0.3.21 → cluxion_agentplugin_preprocessing-0.3.23}/src/cluxion_runtime/cli.py +66 -0
  10. {cluxion_agentplugin_preprocessing-0.3.21 → cluxion_agentplugin_preprocessing-0.3.23}/src/cluxion_runtime/core/harness.py +2 -0
  11. cluxion_agentplugin_preprocessing-0.3.23/src/cluxion_runtime/core/loop_auto.py +443 -0
  12. {cluxion_agentplugin_preprocessing-0.3.21 → cluxion_agentplugin_preprocessing-0.3.23}/src/cluxion_runtime/core/plan_codec.py +1 -0
  13. {cluxion_agentplugin_preprocessing-0.3.21 → cluxion_agentplugin_preprocessing-0.3.23}/src/cluxion_runtime/core/types.py +1 -0
  14. cluxion_agentplugin_preprocessing-0.3.23/tests/runtime/test_loop_auto.py +106 -0
  15. {cluxion_agentplugin_preprocessing-0.3.21 → cluxion_agentplugin_preprocessing-0.3.23}/tests/runtime/test_runtime_adapter_cli.py +2 -0
  16. {cluxion_agentplugin_preprocessing-0.3.21 → cluxion_agentplugin_preprocessing-0.3.23}/tests/test_plugin.py +18 -0
  17. cluxion_agentplugin_preprocessing-0.3.23/tests/test_slash_commands.py +8 -0
  18. {cluxion_agentplugin_preprocessing-0.3.21 → cluxion_agentplugin_preprocessing-0.3.23}/.github/profile/README.md +0 -0
  19. {cluxion_agentplugin_preprocessing-0.3.21 → cluxion_agentplugin_preprocessing-0.3.23}/.gitignore +0 -0
  20. {cluxion_agentplugin_preprocessing-0.3.21 → cluxion_agentplugin_preprocessing-0.3.23}/Docs/README.md +0 -0
  21. {cluxion_agentplugin_preprocessing-0.3.21 → cluxion_agentplugin_preprocessing-0.3.23}/LICENSE +0 -0
  22. {cluxion_agentplugin_preprocessing-0.3.21 → cluxion_agentplugin_preprocessing-0.3.23}/README.md +0 -0
  23. {cluxion_agentplugin_preprocessing-0.3.21 → cluxion_agentplugin_preprocessing-0.3.23}/adapters/claude/.claude-plugin/plugin.json +0 -0
  24. {cluxion_agentplugin_preprocessing-0.3.21 → cluxion_agentplugin_preprocessing-0.3.23}/adapters/claude/skills/preprocess/SKILL.md +0 -0
  25. {cluxion_agentplugin_preprocessing-0.3.21 → cluxion_agentplugin_preprocessing-0.3.23}/adapters/codex/config-snippet.toml +0 -0
  26. {cluxion_agentplugin_preprocessing-0.3.21 → cluxion_agentplugin_preprocessing-0.3.23}/cluxion-Docs/README.md +0 -0
  27. {cluxion_agentplugin_preprocessing-0.3.21 → cluxion_agentplugin_preprocessing-0.3.23}/cluxion-Docs/architecture.md +0 -0
  28. {cluxion_agentplugin_preprocessing-0.3.21 → cluxion_agentplugin_preprocessing-0.3.23}/cluxion-Docs/harness-logic.md +0 -0
  29. {cluxion_agentplugin_preprocessing-0.3.21 → cluxion_agentplugin_preprocessing-0.3.23}/cluxion-Docs/honesty-preprocessing.md +0 -0
  30. {cluxion_agentplugin_preprocessing-0.3.21 → cluxion_agentplugin_preprocessing-0.3.23}/cluxion-Docs/install-and-operations.md +0 -0
  31. {cluxion_agentplugin_preprocessing-0.3.21 → cluxion_agentplugin_preprocessing-0.3.23}/cluxion-Docs/security.md +0 -0
  32. {cluxion_agentplugin_preprocessing-0.3.21 → cluxion_agentplugin_preprocessing-0.3.23}/rust/cluxion_queue/Cargo.lock +0 -0
  33. {cluxion_agentplugin_preprocessing-0.3.21 → cluxion_agentplugin_preprocessing-0.3.23}/rust/cluxion_queue/Cargo.toml +0 -0
  34. {cluxion_agentplugin_preprocessing-0.3.21 → cluxion_agentplugin_preprocessing-0.3.23}/rust/cluxion_queue/pyproject.toml +0 -0
  35. {cluxion_agentplugin_preprocessing-0.3.21 → cluxion_agentplugin_preprocessing-0.3.23}/rust/cluxion_queue/src/context.rs +0 -0
  36. {cluxion_agentplugin_preprocessing-0.3.21 → cluxion_agentplugin_preprocessing-0.3.23}/rust/cluxion_queue/src/dispatch.rs +0 -0
  37. {cluxion_agentplugin_preprocessing-0.3.21 → cluxion_agentplugin_preprocessing-0.3.23}/rust/cluxion_queue/src/guard.rs +0 -0
  38. {cluxion_agentplugin_preprocessing-0.3.21 → cluxion_agentplugin_preprocessing-0.3.23}/rust/cluxion_queue/src/lib.rs +0 -0
  39. {cluxion_agentplugin_preprocessing-0.3.21 → cluxion_agentplugin_preprocessing-0.3.23}/rust/cluxion_queue/src/main.rs +0 -0
  40. {cluxion_agentplugin_preprocessing-0.3.21 → cluxion_agentplugin_preprocessing-0.3.23}/rust/cluxion_queue/src/queue.rs +0 -0
  41. {cluxion_agentplugin_preprocessing-0.3.21 → cluxion_agentplugin_preprocessing-0.3.23}/rust/cluxion_queue/src/types.rs +0 -0
  42. {cluxion_agentplugin_preprocessing-0.3.21 → cluxion_agentplugin_preprocessing-0.3.23}/src/cluxion_agentplugin_preprocessing/__init__.py +0 -0
  43. {cluxion_agentplugin_preprocessing-0.3.21 → cluxion_agentplugin_preprocessing-0.3.23}/src/cluxion_agentplugin_preprocessing/cli.py +0 -0
  44. {cluxion_agentplugin_preprocessing-0.3.21 → cluxion_agentplugin_preprocessing-0.3.23}/src/cluxion_agentplugin_preprocessing/doctor/__init__.py +0 -0
  45. {cluxion_agentplugin_preprocessing-0.3.21 → cluxion_agentplugin_preprocessing-0.3.23}/src/cluxion_agentplugin_preprocessing/doctor/catalog.json +0 -0
  46. {cluxion_agentplugin_preprocessing-0.3.21 → cluxion_agentplugin_preprocessing-0.3.23}/src/cluxion_agentplugin_preprocessing/doctor/framework.py +0 -0
  47. {cluxion_agentplugin_preprocessing-0.3.21 → cluxion_agentplugin_preprocessing-0.3.23}/src/cluxion_agentplugin_preprocessing/doctor/probes.py +0 -0
  48. {cluxion_agentplugin_preprocessing-0.3.21 → cluxion_agentplugin_preprocessing-0.3.23}/src/cluxion_agentplugin_preprocessing/guard_watch.py +0 -0
  49. {cluxion_agentplugin_preprocessing-0.3.21 → cluxion_agentplugin_preprocessing-0.3.23}/src/cluxion_agentplugin_preprocessing/hermes_config.py +0 -0
  50. {cluxion_agentplugin_preprocessing-0.3.21 → cluxion_agentplugin_preprocessing-0.3.23}/src/cluxion_runtime/__init__.py +0 -0
  51. {cluxion_agentplugin_preprocessing-0.3.21 → cluxion_agentplugin_preprocessing-0.3.23}/src/cluxion_runtime/__main__.py +0 -0
  52. {cluxion_agentplugin_preprocessing-0.3.21 → cluxion_agentplugin_preprocessing-0.3.23}/src/cluxion_runtime/adapters/__init__.py +0 -0
  53. {cluxion_agentplugin_preprocessing-0.3.21 → cluxion_agentplugin_preprocessing-0.3.23}/src/cluxion_runtime/adapters/contract.py +0 -0
  54. {cluxion_agentplugin_preprocessing-0.3.21 → cluxion_agentplugin_preprocessing-0.3.23}/src/cluxion_runtime/adapters/grok_build.py +0 -0
  55. {cluxion_agentplugin_preprocessing-0.3.21 → cluxion_agentplugin_preprocessing-0.3.23}/src/cluxion_runtime/adapters/hermes.py +0 -0
  56. {cluxion_agentplugin_preprocessing-0.3.21 → cluxion_agentplugin_preprocessing-0.3.23}/src/cluxion_runtime/adapters/spec.py +0 -0
  57. {cluxion_agentplugin_preprocessing-0.3.21 → cluxion_agentplugin_preprocessing-0.3.23}/src/cluxion_runtime/bootstrap.py +0 -0
  58. {cluxion_agentplugin_preprocessing-0.3.21 → cluxion_agentplugin_preprocessing-0.3.23}/src/cluxion_runtime/core/__init__.py +0 -0
  59. {cluxion_agentplugin_preprocessing-0.3.21 → cluxion_agentplugin_preprocessing-0.3.23}/src/cluxion_runtime/core/clarification.py +0 -0
  60. {cluxion_agentplugin_preprocessing-0.3.21 → cluxion_agentplugin_preprocessing-0.3.23}/src/cluxion_runtime/core/context_compress.py +0 -0
  61. {cluxion_agentplugin_preprocessing-0.3.21 → cluxion_agentplugin_preprocessing-0.3.23}/src/cluxion_runtime/core/dispatch_store.py +0 -0
  62. {cluxion_agentplugin_preprocessing-0.3.21 → cluxion_agentplugin_preprocessing-0.3.23}/src/cluxion_runtime/core/hybrid_forget.py +0 -0
  63. {cluxion_agentplugin_preprocessing-0.3.21 → cluxion_agentplugin_preprocessing-0.3.23}/src/cluxion_runtime/core/intent.py +0 -0
  64. {cluxion_agentplugin_preprocessing-0.3.21 → cluxion_agentplugin_preprocessing-0.3.23}/src/cluxion_runtime/core/ledger.py +0 -0
  65. {cluxion_agentplugin_preprocessing-0.3.21 → cluxion_agentplugin_preprocessing-0.3.23}/src/cluxion_runtime/core/ledger_codec.py +0 -0
  66. {cluxion_agentplugin_preprocessing-0.3.21 → cluxion_agentplugin_preprocessing-0.3.23}/src/cluxion_runtime/core/llm_compress.py +0 -0
  67. {cluxion_agentplugin_preprocessing-0.3.21 → cluxion_agentplugin_preprocessing-0.3.23}/src/cluxion_runtime/core/preprocess.py +0 -0
  68. {cluxion_agentplugin_preprocessing-0.3.21 → cluxion_agentplugin_preprocessing-0.3.23}/src/cluxion_runtime/core/work_queue.py +0 -0
  69. {cluxion_agentplugin_preprocessing-0.3.21 → cluxion_agentplugin_preprocessing-0.3.23}/src/cluxion_runtime/guard_daemon_host.py +0 -0
  70. {cluxion_agentplugin_preprocessing-0.3.21 → cluxion_agentplugin_preprocessing-0.3.23}/src/cluxion_runtime/models/__init__.py +0 -0
  71. {cluxion_agentplugin_preprocessing-0.3.21 → cluxion_agentplugin_preprocessing-0.3.23}/src/cluxion_runtime/models/supervisor.py +0 -0
  72. {cluxion_agentplugin_preprocessing-0.3.21 → cluxion_agentplugin_preprocessing-0.3.23}/src/cluxion_runtime/models/vllm_mlx.py +0 -0
  73. {cluxion_agentplugin_preprocessing-0.3.21 → cluxion_agentplugin_preprocessing-0.3.23}/src/cluxion_runtime/resources/__init__.py +0 -0
  74. {cluxion_agentplugin_preprocessing-0.3.21 → cluxion_agentplugin_preprocessing-0.3.23}/src/cluxion_runtime/resources/guard_bridge.py +0 -0
  75. {cluxion_agentplugin_preprocessing-0.3.21 → cluxion_agentplugin_preprocessing-0.3.23}/src/cluxion_runtime/resources/py_queue.py +0 -0
  76. {cluxion_agentplugin_preprocessing-0.3.21 → cluxion_agentplugin_preprocessing-0.3.23}/src/cluxion_runtime/resources/queue_bridge.py +0 -0
  77. {cluxion_agentplugin_preprocessing-0.3.21 → cluxion_agentplugin_preprocessing-0.3.23}/src/cluxion_runtime/resources/rust_bridge.py +0 -0
  78. {cluxion_agentplugin_preprocessing-0.3.21 → cluxion_agentplugin_preprocessing-0.3.23}/src/cluxion_runtime/web/__init__.py +0 -0
  79. {cluxion_agentplugin_preprocessing-0.3.21 → cluxion_agentplugin_preprocessing-0.3.23}/src/cluxion_runtime/web/browser_bridge.py +0 -0
  80. {cluxion_agentplugin_preprocessing-0.3.21 → cluxion_agentplugin_preprocessing-0.3.23}/tests/runtime/test_auto_compress_middleware.py +0 -0
  81. {cluxion_agentplugin_preprocessing-0.3.21 → cluxion_agentplugin_preprocessing-0.3.23}/tests/runtime/test_bin_resolution.py +0 -0
  82. {cluxion_agentplugin_preprocessing-0.3.21 → cluxion_agentplugin_preprocessing-0.3.23}/tests/runtime/test_browser_bridge.py +0 -0
  83. {cluxion_agentplugin_preprocessing-0.3.21 → cluxion_agentplugin_preprocessing-0.3.23}/tests/runtime/test_clarification.py +0 -0
  84. {cluxion_agentplugin_preprocessing-0.3.21 → cluxion_agentplugin_preprocessing-0.3.23}/tests/runtime/test_cluxion_runtime_spine.py +0 -0
  85. {cluxion_agentplugin_preprocessing-0.3.21 → cluxion_agentplugin_preprocessing-0.3.23}/tests/runtime/test_context_compress.py +0 -0
  86. {cluxion_agentplugin_preprocessing-0.3.21 → cluxion_agentplugin_preprocessing-0.3.23}/tests/runtime/test_context_compress_llm_forget.py +0 -0
  87. {cluxion_agentplugin_preprocessing-0.3.21 → cluxion_agentplugin_preprocessing-0.3.23}/tests/runtime/test_contract.py +0 -0
  88. {cluxion_agentplugin_preprocessing-0.3.21 → cluxion_agentplugin_preprocessing-0.3.23}/tests/runtime/test_dispatch_store.py +0 -0
  89. {cluxion_agentplugin_preprocessing-0.3.21 → cluxion_agentplugin_preprocessing-0.3.23}/tests/runtime/test_estimate_tokens.py +0 -0
  90. {cluxion_agentplugin_preprocessing-0.3.21 → cluxion_agentplugin_preprocessing-0.3.23}/tests/runtime/test_guard.py +0 -0
  91. {cluxion_agentplugin_preprocessing-0.3.21 → cluxion_agentplugin_preprocessing-0.3.23}/tests/runtime/test_guard_daemon_host.py +0 -0
  92. {cluxion_agentplugin_preprocessing-0.3.21 → cluxion_agentplugin_preprocessing-0.3.23}/tests/runtime/test_ledger.py +0 -0
  93. {cluxion_agentplugin_preprocessing-0.3.21 → cluxion_agentplugin_preprocessing-0.3.23}/tests/runtime/test_py_queue_concurrency.py +0 -0
  94. {cluxion_agentplugin_preprocessing-0.3.21 → cluxion_agentplugin_preprocessing-0.3.23}/tests/runtime/test_queue_backends.py +0 -0
  95. {cluxion_agentplugin_preprocessing-0.3.21 → cluxion_agentplugin_preprocessing-0.3.23}/tests/runtime/test_rust_queue.py +0 -0
  96. {cluxion_agentplugin_preprocessing-0.3.21 → cluxion_agentplugin_preprocessing-0.3.23}/tests/runtime/test_supervisor.py +0 -0
  97. {cluxion_agentplugin_preprocessing-0.3.21 → cluxion_agentplugin_preprocessing-0.3.23}/tests/test_bootstrap.py +0 -0
  98. {cluxion_agentplugin_preprocessing-0.3.21 → cluxion_agentplugin_preprocessing-0.3.23}/tests/test_doctor.py +0 -0
  99. {cluxion_agentplugin_preprocessing-0.3.21 → cluxion_agentplugin_preprocessing-0.3.23}/tests/test_guard_watch.py +0 -0
  100. {cluxion_agentplugin_preprocessing-0.3.21 → cluxion_agentplugin_preprocessing-0.3.23}/tests/test_hermes_config.py +0 -0
  101. {cluxion_agentplugin_preprocessing-0.3.21 → cluxion_agentplugin_preprocessing-0.3.23}/tests/test_packaging_policy.py +0 -0
  102. {cluxion_agentplugin_preprocessing-0.3.21 → cluxion_agentplugin_preprocessing-0.3.23}/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.21
3
+ Version: 0.3.23
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.21"
7
+ version = "0.3.23"
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"
@@ -0,0 +1,8 @@
1
+ version = 1
2
+ revision = 3
3
+ requires-python = ">=3.11"
4
+
5
+ [[package]]
6
+ name = "cluxion-queue-native"
7
+ version = "0.2.1"
8
+ source = { editable = "." }
@@ -20,6 +20,7 @@ from cluxion_agentplugin_preprocessing.schemas import (
20
20
  CONTEXT_COMPRESS_SCHEMA,
21
21
  GUARD_SCHEMA,
22
22
  HERMES_CONFIG_SCHEMA,
23
+ LOOP_AUTO_SCHEMA,
23
24
  PLAN_SCHEMA,
24
25
  QUEUE_BRIEF_SCHEMA,
25
26
  QUEUE_NEXT_SCHEMA,
@@ -27,11 +28,13 @@ from cluxion_agentplugin_preprocessing.schemas import (
27
28
  SERVE_LOCAL_SCHEMA,
28
29
  WEB_SEARCH_SCHEMA,
29
30
  )
31
+ from cluxion_agentplugin_preprocessing.slash_commands import register_slash_commands
30
32
  from cluxion_runtime.core.context_compress import (
31
33
  DEFAULT_TRIGGER_RATIO,
32
34
  _resolve_context_limit,
33
35
  compress,
34
36
  )
37
+ from cluxion_runtime.core.loop_auto import strip_loop_auto_directive
35
38
  from cluxion_runtime.core.preprocess import estimate_tokens
36
39
 
37
40
  if TYPE_CHECKING:
@@ -40,6 +43,7 @@ if TYPE_CHECKING:
40
43
 
41
44
  def register(ctx: object) -> None:
42
45
  """Register Cluxion preprocessing tools with the host agent."""
46
+ register_slash_commands(ctx)
43
47
  register_hook = getattr(ctx, "register_hook", None)
44
48
  if callable(register_hook):
45
49
  register_hook("on_session_start", guard_watch.on_session_start)
@@ -114,6 +118,14 @@ def register(ctx: object) -> None:
114
118
  check_fn=_check_runtime_available,
115
119
  emoji="📌",
116
120
  )
121
+ ctx.register_tool(
122
+ name="cluxion_loop_auto",
123
+ toolset="cluxion",
124
+ schema=LOOP_AUTO_SCHEMA,
125
+ handler=_handle_loop_auto,
126
+ check_fn=_check_runtime_available,
127
+ emoji="🔁",
128
+ )
117
129
  ctx.register_tool(
118
130
  name="cluxion_context_compress",
119
131
  toolset="cluxion",
@@ -201,7 +213,17 @@ def _check_browser_tool_available() -> bool:
201
213
 
202
214
 
203
215
  def _handle_plan(args: dict[str, object], **_: object) -> str:
204
- return _json_result(lambda: runner.plan(args).to_json())
216
+ return _json_result(lambda: runner.plan(_plan_args_with_loop_auto(args)).to_json())
217
+
218
+
219
+ def _plan_args_with_loop_auto(args: dict[str, object]) -> dict[str, object]:
220
+ payload = dict(args)
221
+ prompt = str(payload.get("prompt", ""))
222
+ cleaned, had_directive = strip_loop_auto_directive(prompt)
223
+ if had_directive:
224
+ payload["prompt"] = cleaned
225
+ payload["loop_auto"] = True
226
+ return payload
205
227
 
206
228
 
207
229
  def _handle_clarify(args: dict[str, object], **_: object) -> str:
@@ -232,6 +254,10 @@ def _handle_queue_brief(args: dict[str, object], **_: object) -> str:
232
254
  return _json_result(lambda: runner.queue_brief(args).to_json())
233
255
 
234
256
 
257
+ def _handle_loop_auto(args: dict[str, object], **_: object) -> str:
258
+ return _json_result(lambda: runner.loop_auto(args).to_json())
259
+
260
+
235
261
  def _handle_context_compress(args: dict[str, object], **_: object) -> str:
236
262
  return _json_result(lambda: runner.context_compress(args).to_json())
237
263
 
@@ -1,5 +1,5 @@
1
1
  name: cluxion-agentplugin-preprocessing
2
- version: 0.3.20
2
+ version: 0.3.23
3
3
  description: "Universal agent preprocessing plugin: honesty contracts, clarification, Rust work queue, resource-aware harness handoff. Connected AI calls cluxion tools; plugin does not own models."
4
4
  author: cluxion
5
5
  kind: standalone
@@ -12,6 +12,7 @@ provides_tools:
12
12
  - cluxion_queue_next
13
13
  - cluxion_queue_record
14
14
  - cluxion_queue_brief
15
+ - cluxion_loop_auto
15
16
  - cluxion_context_compress
16
17
  - cluxion_guard
17
18
  - cluxion_web_search
@@ -144,6 +144,19 @@ def queue_brief(payload: Mapping[str, object], *, command_runner: CommandRunner
144
144
  return _execute_json(command, None, command_runner)
145
145
 
146
146
 
147
+ def loop_auto(payload: Mapping[str, object], *, command_runner: CommandRunner | None = None) -> RuntimeResult:
148
+ """Autonomously drain the dispatch queue via Hermes oneshot calls (/loopAuto)."""
149
+ command = (
150
+ _runtime_binary(None),
151
+ "loop-auto",
152
+ "--work-id",
153
+ _required_str(payload, "work_id"),
154
+ "--json-stdin",
155
+ )
156
+ stdin = json.dumps(dict(payload), ensure_ascii=False)
157
+ return _execute_json(command, stdin, command_runner)
158
+
159
+
147
160
  def context_compress(payload: Mapping[str, object], *, command_runner: CommandRunner | None = None) -> RuntimeResult:
148
161
  """Compress conversation context deterministically once it exceeds the trigger ratio."""
149
162
  messages = payload.get("messages")
@@ -367,6 +380,7 @@ __all__ = [
367
380
  "context_compress",
368
381
  "guard",
369
382
  "hermes_config",
383
+ "loop_auto",
370
384
  "plan",
371
385
  "queue_brief",
372
386
  "queue_next",
@@ -58,6 +58,31 @@ PLAN_SCHEMA = {
58
58
  "default": "",
59
59
  "description": "Answers that resolve a prior clarification gate; required to enqueue an ambiguous or large task.",
60
60
  },
61
+ "loop_auto": {
62
+ "type": "boolean",
63
+ "default": True,
64
+ "description": "After a queued plan is stored, autonomously drain segments via Hermes oneshot calls.",
65
+ },
66
+ "loop_auto_dry_run": {
67
+ "type": "boolean",
68
+ "default": False,
69
+ "description": "Simulate Hermes segment execution without calling the hermes binary.",
70
+ },
71
+ "loop_auto_timeout_s": {
72
+ "type": "number",
73
+ "default": 600,
74
+ "description": "Maximum seconds for the full autonomous drain loop.",
75
+ },
76
+ "hermes_bin": {
77
+ "type": "string",
78
+ "default": "hermes",
79
+ "description": "Hermes CLI binary used for each segment oneshot.",
80
+ },
81
+ "model": {
82
+ "type": "string",
83
+ "default": "",
84
+ "description": "Optional Hermes model override (-m) for segment oneshots.",
85
+ },
61
86
  },
62
87
  "required": ["prompt"],
63
88
  },
@@ -142,6 +167,32 @@ QUEUE_BRIEF_SCHEMA = {
142
167
  },
143
168
  }
144
169
 
170
+ LOOP_AUTO_SCHEMA = {
171
+ "name": "cluxion_loop_auto",
172
+ "description": (
173
+ "Autonomously drain the Cluxion dispatch queue via Hermes oneshot calls. "
174
+ "Equivalent to /loopAuto: next segment -> hermes -z -> record -> ... -> briefing. "
175
+ "Use after cluxion_plan queued a durable work bundle, or pass loop_auto on plan."
176
+ ),
177
+ "parameters": {
178
+ "type": "object",
179
+ "properties": {
180
+ "work_id": {"type": "string", "description": "Queued work bundle id from cluxion_plan."},
181
+ "cwd": {"type": "string", "default": ""},
182
+ "hermes_bin": {"type": "string", "default": "hermes"},
183
+ "model": {"type": "string", "default": ""},
184
+ "timeout_seconds": {"type": "number", "default": 600},
185
+ "max_segment_retries": {"type": "integer", "minimum": 0, "default": 2},
186
+ "dry_run": {
187
+ "type": "boolean",
188
+ "default": False,
189
+ "description": "Simulate Hermes without calling the binary (tests and diagnostics).",
190
+ },
191
+ },
192
+ "required": ["work_id"],
193
+ },
194
+ }
195
+
145
196
  CONTEXT_COMPRESS_SCHEMA = {
146
197
  "name": "cluxion_context_compress",
147
198
  "description": (
@@ -370,6 +421,7 @@ __all__ = [
370
421
  "CONTEXT_COMPRESS_SCHEMA",
371
422
  "GUARD_SCHEMA",
372
423
  "HERMES_CONFIG_SCHEMA",
424
+ "LOOP_AUTO_SCHEMA",
373
425
  "PLAN_SCHEMA",
374
426
  "QUEUE_BRIEF_SCHEMA",
375
427
  "QUEUE_NEXT_SCHEMA",
@@ -0,0 +1,121 @@
1
+ """In-session slash commands for Hermes (/loopauto, /cluxion-doctor)."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import json
6
+ from pathlib import Path
7
+
8
+ from cluxion_agentplugin_preprocessing import runner
9
+ from cluxion_agentplugin_preprocessing.doctor import render_text, run_doctor
10
+ from cluxion_agentplugin_preprocessing.doctor.probes import PROBES
11
+
12
+ LOOPAUTO_HELP = """\
13
+ /loopauto <prompt> — Autonomous queue drain (loopAuto)
14
+
15
+ Plans the task, stores segment content in the Rust queue, then loops:
16
+ queue_next → hermes -z → queue_record → … → briefing
17
+
18
+ Examples:
19
+ /loopauto implement every REQ line and record evidence
20
+ /loopauto refactor auth module with tests
21
+
22
+ Notes:
23
+ - Equivalent to prefixing a prompt with /loopAuto on cluxion_plan
24
+ - Disable auto-loop: export CLUXION_LOOP_AUTO=0
25
+ - Diagnostics only: add loop_auto_dry_run via cluxion_plan tool
26
+ """
27
+
28
+ CLUXION_DOCTOR_HELP = "/cluxion-doctor — Run preprocessing plugin health checks (doctor)."
29
+
30
+
31
+ def register_slash_commands(ctx: object) -> None:
32
+ register = getattr(ctx, "register_command", None)
33
+ if not callable(register):
34
+ return
35
+ register(
36
+ "loopauto",
37
+ handle_loopauto,
38
+ description="Autonomous queue drain (loopAuto) — plan + Hermes oneshot segment loop",
39
+ args_hint="<prompt>",
40
+ )
41
+ register(
42
+ "cluxion-doctor",
43
+ handle_cluxion_doctor,
44
+ description="Run cluxion preprocessing plugin doctor checks",
45
+ )
46
+
47
+
48
+ def handle_loopauto(raw_args: str) -> str:
49
+ prompt = raw_args.strip()
50
+ if not prompt or prompt.lower() in {"help", "-h", "--help"}:
51
+ return LOOPAUTO_HELP
52
+ try:
53
+ result = runner.plan(
54
+ {
55
+ "prompt": f"/loopAuto {prompt}",
56
+ "cwd": str(Path.cwd()),
57
+ "clarification_answers": "confirmed via /loopauto slash command",
58
+ }
59
+ )
60
+ return _format_plan_response(result.to_json())
61
+ except Exception as exc:
62
+ return f"loopauto error: {exc}"
63
+
64
+
65
+ def handle_cluxion_doctor(raw_args: str) -> str:
66
+ if raw_args.strip().lower() in {"help", "-h", "--help"}:
67
+ return CLUXION_DOCTOR_HELP
68
+ import importlib.resources
69
+
70
+ from cluxion_agentplugin_preprocessing import __version__
71
+ from cluxion_agentplugin_preprocessing.doctor.framework import load_catalog
72
+
73
+ pkg = "cluxion_agentplugin_preprocessing.doctor"
74
+ catalog_path = Path(str(importlib.resources.files(pkg).joinpath("catalog.json")))
75
+ result = run_doctor(
76
+ cwd=Path.cwd(),
77
+ hermes_bin="hermes",
78
+ catalog_path=catalog_path,
79
+ probes=PROBES,
80
+ plugin="preprocessing",
81
+ version=__version__,
82
+ )
83
+ return render_text(result, load_catalog(catalog_path))
84
+
85
+
86
+ def _format_plan_response(raw_json: str) -> str:
87
+ payload = json.loads(raw_json)
88
+ if not payload.get("ok"):
89
+ return f"loopauto failed: {payload.get('error', 'unknown error')}"
90
+ body = payload.get("result", payload)
91
+ if not isinstance(body, dict):
92
+ return str(body)
93
+ loop = body.get("loop_auto")
94
+ if isinstance(loop, dict):
95
+ lines = [
96
+ f"[loopauto] ok={loop.get('ok')} status={loop.get('status')}",
97
+ f"segments_processed={loop.get('segments_processed')} "
98
+ f"segments_failed={loop.get('segments_failed')} "
99
+ f"duration_ms={loop.get('duration_ms')}",
100
+ ]
101
+ if loop.get("error"):
102
+ lines.append(f"error: {loop['error']}")
103
+ briefing = str(loop.get("briefing_answer", "")).strip()
104
+ if briefing:
105
+ lines.extend(["", briefing])
106
+ return "\n".join(lines)
107
+ host = body.get("host_execution")
108
+ if isinstance(host, dict) and host.get("queue_required"):
109
+ return (
110
+ "Plan queued but loop_auto did not run. "
111
+ "Check CLUXION_LOOP_AUTO=1 and hermes on PATH (cluxion-preprocess doctor)."
112
+ )
113
+ return json.dumps(body, ensure_ascii=False, indent=2)[:8000]
114
+
115
+
116
+ __all__ = [
117
+ "LOOPAUTO_HELP",
118
+ "handle_cluxion_doctor",
119
+ "handle_loopauto",
120
+ "register_slash_commands",
121
+ ]
@@ -5,6 +5,7 @@ from __future__ import annotations
5
5
  import argparse
6
6
  import json
7
7
  import sys
8
+ from pathlib import Path
8
9
  from typing import TYPE_CHECKING
9
10
 
10
11
  from cluxion_runtime.adapters.contract import work_item_from_adapter_payload
@@ -23,6 +24,12 @@ from cluxion_runtime.core.dispatch_store import (
23
24
  record_dispatch_result,
24
25
  )
25
26
  from cluxion_runtime.core.harness import build_harness_plan
27
+ from cluxion_runtime.core.loop_auto import (
28
+ LoopAutoOptions,
29
+ run_loop_auto,
30
+ should_auto_loop_plan,
31
+ strip_loop_auto_directive,
32
+ )
26
33
  from cluxion_runtime.core.plan_codec import plan_to_dict
27
34
  from cluxion_runtime.core.types import AgentSurface, ModelRuntimeProfile
28
35
  from cluxion_runtime.models import LocalModelSupervisor, build_vllm_mlx_profile
@@ -49,6 +56,8 @@ def main(argv: Sequence[str] | None = None) -> int:
49
56
  return _run_queue_record(args)
50
57
  if args.command == "queue-brief":
51
58
  return _run_queue_brief(args)
59
+ if args.command == "loop-auto":
60
+ return _run_loop_auto(args)
52
61
  if args.command == "context-compress":
53
62
  return _run_context_compress(args)
54
63
  if args.command == "guard":
@@ -111,6 +120,18 @@ def _build_parser() -> argparse.ArgumentParser:
111
120
  "queue-brief", help="Build the final briefing prompt from stored segment results"
112
121
  )
113
122
  queue_brief.add_argument("--work-id", required=True)
123
+ loop_auto = subparsers.add_parser(
124
+ "loop-auto",
125
+ help="Autonomously drain the dispatch queue via Hermes oneshot calls (/loopAuto)",
126
+ )
127
+ loop_auto.add_argument("--work-id", required=True)
128
+ loop_auto.add_argument("--cwd", default="")
129
+ loop_auto.add_argument("--hermes-bin", default="hermes")
130
+ loop_auto.add_argument("--model", default="")
131
+ loop_auto.add_argument("--timeout-seconds", type=float, default=600.0)
132
+ loop_auto.add_argument("--max-segment-retries", type=int, default=2)
133
+ loop_auto.add_argument("--dry-run", action="store_true")
134
+ loop_auto.add_argument("--json-stdin", action="store_true")
114
135
  context_compress = subparsers.add_parser(
115
136
  "context-compress",
116
137
  help="Deterministically compress conversation context to the target ratio once past the trigger ratio",
@@ -137,6 +158,7 @@ def _run_bootstrap(args: argparse.Namespace) -> int:
137
158
  def _run_plan(args: argparse.Namespace) -> int:
138
159
  surface = AgentSurface(str(args.surface))
139
160
  payload = _payload_from_stdin() if args.json_stdin else _payload_from_args(args)
161
+ payload = _apply_loop_auto_directive(payload)
140
162
  item = work_item_from_adapter_payload(payload, default_surface=surface)
141
163
  plan = build_harness_plan(item)
142
164
  persisted = persist_dispatch_bundle(plan)
@@ -146,10 +168,43 @@ def _run_plan(args: argparse.Namespace) -> int:
146
168
  if isinstance(item_output, dict):
147
169
  item_output["original_prompt_stored"] = True
148
170
  output["dispatch_store"] = {"stored": True, "path": str(persisted)}
171
+ loop_auto_flag = payload.get("loop_auto") if isinstance(payload, dict) else None
172
+ if should_auto_loop_plan(output, loop_auto=bool(loop_auto_flag) if loop_auto_flag is not None else None):
173
+ cwd = str(payload.get("cwd", "")) if isinstance(payload, dict) else ""
174
+ loop_result = run_loop_auto(
175
+ LoopAutoOptions(
176
+ work_id=plan.item.work_id,
177
+ cwd=Path(cwd).expanduser() if cwd else Path.cwd(),
178
+ hermes_bin=str(payload.get("hermes_bin", "hermes")) if isinstance(payload, dict) else "hermes",
179
+ model=str(payload.get("model", "")) if isinstance(payload, dict) else "",
180
+ timeout_seconds=float(payload.get("loop_auto_timeout_s", 600)) if isinstance(payload, dict) else 600.0,
181
+ dry_run=bool(payload.get("loop_auto_dry_run", False)) if isinstance(payload, dict) else False,
182
+ )
183
+ )
184
+ output["loop_auto"] = loop_result.to_dict()
149
185
  print(json.dumps(output, ensure_ascii=False, sort_keys=True))
150
186
  return 0
151
187
 
152
188
 
189
+ def _run_loop_auto(args: argparse.Namespace) -> int:
190
+ payload = _payload_from_stdin() if args.json_stdin else {}
191
+ work_id = str(payload.get("work_id", args.work_id))
192
+ cwd_raw = str(payload.get("cwd", args.cwd))
193
+ result = run_loop_auto(
194
+ LoopAutoOptions(
195
+ work_id=work_id,
196
+ cwd=Path(cwd_raw).expanduser() if cwd_raw else Path.cwd(),
197
+ hermes_bin=str(payload.get("hermes_bin", args.hermes_bin)),
198
+ model=str(payload.get("model", args.model)),
199
+ timeout_seconds=float(payload.get("timeout_seconds", args.timeout_seconds)),
200
+ max_segment_retries=int(payload.get("max_segment_retries", args.max_segment_retries)),
201
+ dry_run=bool(payload.get("dry_run", args.dry_run)),
202
+ )
203
+ )
204
+ print(json.dumps(result.to_dict(), ensure_ascii=False, sort_keys=True))
205
+ return 0 if result.ok else 1
206
+
207
+
153
208
  def _run_queue_next(args: argparse.Namespace) -> int:
154
209
  try:
155
210
  payload = next_dispatch_step(str(args.work_id))
@@ -389,6 +444,17 @@ def _payload_from_args(args: argparse.Namespace) -> dict[str, object]:
389
444
  }
390
445
 
391
446
 
447
+ def _apply_loop_auto_directive(payload: dict[str, object]) -> dict[str, object]:
448
+ prompt = str(payload.get("prompt", ""))
449
+ cleaned, had_directive = strip_loop_auto_directive(prompt)
450
+ if not had_directive:
451
+ return payload
452
+ updated = dict(payload)
453
+ updated["prompt"] = cleaned
454
+ updated["loop_auto"] = True
455
+ return updated
456
+
457
+
392
458
  if __name__ == "__main__":
393
459
  raise SystemExit(main())
394
460
 
@@ -201,10 +201,12 @@ def _host_execution_plan_for(
201
201
  next_tool="cluxion_queue_next",
202
202
  record_tool="cluxion_queue_record",
203
203
  brief_tool="cluxion_queue_brief",
204
+ loop_tool="cluxion_loop_auto",
204
205
  performance_notes=(
205
206
  *base_notes,
206
207
  "queued_plan_stores_segment_content_out_of_band",
207
208
  "initial_plan_returns_metadata_not_full_segment_payload",
209
+ "use_cluxion_loop_auto_or_slash_loopAuto_for_autonomous_drain",
208
210
  ),
209
211
  )
210
212
  return HostExecutionPlan(