@miller-tech/uap 2.11.1 → 2.16.4

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 (160) hide show
  1. package/config/capacity-policy.json +15 -3
  2. package/config/model-profiles/qwen38.json +42 -34
  3. package/dist/.tsbuildinfo +1 -1
  4. package/dist/bin/cli.js +39 -0
  5. package/dist/bin/cli.js.map +1 -1
  6. package/dist/capacity/policy.d.ts +15 -0
  7. package/dist/capacity/policy.d.ts.map +1 -1
  8. package/dist/capacity/policy.js +23 -0
  9. package/dist/capacity/policy.js.map +1 -1
  10. package/dist/capacity/probe.d.ts.map +1 -1
  11. package/dist/capacity/probe.js +6 -1
  12. package/dist/capacity/probe.js.map +1 -1
  13. package/dist/cli/deliver.d.ts.map +1 -1
  14. package/dist/cli/deliver.js +148 -2
  15. package/dist/cli/deliver.js.map +1 -1
  16. package/dist/cli/inference.d.ts +13 -0
  17. package/dist/cli/inference.d.ts.map +1 -0
  18. package/dist/cli/inference.js +132 -0
  19. package/dist/cli/inference.js.map +1 -0
  20. package/dist/cli/loops.d.ts +39 -0
  21. package/dist/cli/loops.d.ts.map +1 -0
  22. package/dist/cli/loops.js +154 -0
  23. package/dist/cli/loops.js.map +1 -0
  24. package/dist/cli/wizard-config.d.ts.map +1 -1
  25. package/dist/cli/wizard-config.js +5 -1
  26. package/dist/cli/wizard-config.js.map +1 -1
  27. package/dist/cli/worktree.d.ts.map +1 -1
  28. package/dist/cli/worktree.js +8 -4
  29. package/dist/cli/worktree.js.map +1 -1
  30. package/dist/delivery/adversarial-attack.d.ts +99 -0
  31. package/dist/delivery/adversarial-attack.d.ts.map +1 -0
  32. package/dist/delivery/adversarial-attack.js +326 -0
  33. package/dist/delivery/adversarial-attack.js.map +1 -0
  34. package/dist/delivery/adversarial-gate.d.ts +120 -0
  35. package/dist/delivery/adversarial-gate.d.ts.map +1 -0
  36. package/dist/delivery/adversarial-gate.js +259 -0
  37. package/dist/delivery/adversarial-gate.js.map +1 -0
  38. package/dist/delivery/adversarial-sanction.d.ts +52 -0
  39. package/dist/delivery/adversarial-sanction.d.ts.map +1 -0
  40. package/dist/delivery/adversarial-sanction.js +134 -0
  41. package/dist/delivery/adversarial-sanction.js.map +1 -0
  42. package/dist/delivery/agentic-executor.d.ts +69 -22
  43. package/dist/delivery/agentic-executor.d.ts.map +1 -1
  44. package/dist/delivery/agentic-executor.js +152 -8
  45. package/dist/delivery/agentic-executor.js.map +1 -1
  46. package/dist/delivery/applier.d.ts +8 -0
  47. package/dist/delivery/applier.d.ts.map +1 -1
  48. package/dist/delivery/applier.js +3 -1
  49. package/dist/delivery/applier.js.map +1 -1
  50. package/dist/delivery/convergence-loop.d.ts +15 -0
  51. package/dist/delivery/convergence-loop.d.ts.map +1 -1
  52. package/dist/delivery/convergence-loop.js.map +1 -1
  53. package/dist/delivery/criteria-lint.d.ts +74 -0
  54. package/dist/delivery/criteria-lint.d.ts.map +1 -0
  55. package/dist/delivery/criteria-lint.js +134 -0
  56. package/dist/delivery/criteria-lint.js.map +1 -0
  57. package/dist/delivery/deliver-toggle.d.ts +21 -0
  58. package/dist/delivery/deliver-toggle.d.ts.map +1 -0
  59. package/dist/delivery/deliver-toggle.js +40 -0
  60. package/dist/delivery/deliver-toggle.js.map +1 -0
  61. package/dist/delivery/delivery-evidence.d.ts +109 -0
  62. package/dist/delivery/delivery-evidence.d.ts.map +1 -0
  63. package/dist/delivery/delivery-evidence.js +139 -0
  64. package/dist/delivery/delivery-evidence.js.map +1 -0
  65. package/dist/delivery/epic-mission.d.ts +5 -1
  66. package/dist/delivery/epic-mission.d.ts.map +1 -1
  67. package/dist/delivery/epic-mission.js +34 -6
  68. package/dist/delivery/epic-mission.js.map +1 -1
  69. package/dist/delivery/execution-gate.d.ts.map +1 -1
  70. package/dist/delivery/execution-gate.js +90 -7
  71. package/dist/delivery/execution-gate.js.map +1 -1
  72. package/dist/delivery/index.d.ts +9 -1
  73. package/dist/delivery/index.d.ts.map +1 -1
  74. package/dist/delivery/index.js +9 -1
  75. package/dist/delivery/index.js.map +1 -1
  76. package/dist/delivery/journey-depth.d.ts +61 -0
  77. package/dist/delivery/journey-depth.d.ts.map +1 -0
  78. package/dist/delivery/journey-depth.js +91 -0
  79. package/dist/delivery/journey-depth.js.map +1 -0
  80. package/dist/delivery/master-pipeline.d.ts +50 -0
  81. package/dist/delivery/master-pipeline.d.ts.map +1 -0
  82. package/dist/delivery/master-pipeline.js +52 -0
  83. package/dist/delivery/master-pipeline.js.map +1 -0
  84. package/dist/delivery/mission-acceptance.d.ts.map +1 -1
  85. package/dist/delivery/mission-acceptance.js +54 -2
  86. package/dist/delivery/mission-acceptance.js.map +1 -1
  87. package/dist/delivery/orchestrated-mission.d.ts +4 -1
  88. package/dist/delivery/orchestrated-mission.d.ts.map +1 -1
  89. package/dist/delivery/orchestrated-mission.js +18 -9
  90. package/dist/delivery/orchestrated-mission.js.map +1 -1
  91. package/dist/delivery/plan-check.d.ts +1 -0
  92. package/dist/delivery/plan-check.d.ts.map +1 -1
  93. package/dist/delivery/plan-check.js +48 -0
  94. package/dist/delivery/plan-check.js.map +1 -1
  95. package/dist/delivery/task-orchestrator.d.ts +16 -9
  96. package/dist/delivery/task-orchestrator.d.ts.map +1 -1
  97. package/dist/delivery/task-orchestrator.js +4 -2
  98. package/dist/delivery/task-orchestrator.js.map +1 -1
  99. package/dist/delivery/task-workspace.d.ts +35 -5
  100. package/dist/delivery/task-workspace.d.ts.map +1 -1
  101. package/dist/delivery/task-workspace.js +53 -7
  102. package/dist/delivery/task-workspace.js.map +1 -1
  103. package/dist/delivery/test-oracle-additive.d.ts +26 -6
  104. package/dist/delivery/test-oracle-additive.d.ts.map +1 -1
  105. package/dist/delivery/test-oracle-additive.js +40 -15
  106. package/dist/delivery/test-oracle-additive.js.map +1 -1
  107. package/dist/delivery/user-validation.d.ts +14 -0
  108. package/dist/delivery/user-validation.d.ts.map +1 -1
  109. package/dist/delivery/user-validation.js +103 -9
  110. package/dist/delivery/user-validation.js.map +1 -1
  111. package/dist/delivery/verifier-ladder.d.ts.map +1 -1
  112. package/dist/delivery/verifier-ladder.js +24 -6
  113. package/dist/delivery/verifier-ladder.js.map +1 -1
  114. package/dist/inference/analysis.d.ts +138 -0
  115. package/dist/inference/analysis.d.ts.map +1 -0
  116. package/dist/inference/analysis.js +243 -0
  117. package/dist/inference/analysis.js.map +1 -0
  118. package/dist/inference/probe.d.ts +85 -0
  119. package/dist/inference/probe.d.ts.map +1 -0
  120. package/dist/inference/probe.js +403 -0
  121. package/dist/inference/probe.js.map +1 -0
  122. package/dist/models/types.d.ts.map +1 -1
  123. package/dist/models/types.js +45 -18
  124. package/dist/models/types.js.map +1 -1
  125. package/dist/self-tuning/profiles/qwen38.d.ts +17 -8
  126. package/dist/self-tuning/profiles/qwen38.d.ts.map +1 -1
  127. package/dist/self-tuning/profiles/qwen38.js +21 -11
  128. package/dist/self-tuning/profiles/qwen38.js.map +1 -1
  129. package/dist/utils/model-slots.d.ts +11 -5
  130. package/dist/utils/model-slots.d.ts.map +1 -1
  131. package/dist/utils/model-slots.js +11 -5
  132. package/dist/utils/model-slots.js.map +1 -1
  133. package/docs/INDEX.md +1 -0
  134. package/docs/guides/CAPACITY_POLICY.md +24 -0
  135. package/docs/guides/INFERENCE_HEALTH.md +184 -0
  136. package/docs/guides/PROXY.md +1 -0
  137. package/docs/guides/QWEN38_EXL3.md +268 -0
  138. package/docs/plans/hlg-master-architecture-uplift-2026-09-24.md +67 -0
  139. package/docs/reference/CONFIGURATION.md +10 -1
  140. package/docs/reference/CONFIGURATION_REFERENCE.md +14 -0
  141. package/package.json +2 -2
  142. package/scripts/lib/llama-upstream.sh +7 -1
  143. package/src/policies/enforcers/__pycache__/_common.cpython-312.pyc +0 -0
  144. package/src/policies/enforcers/__pycache__/expert_review_required.cpython-312.pyc +0 -0
  145. package/src/policies/enforcers/__pycache__/quality_metrics_gate.cpython-312.pyc +0 -0
  146. package/src/policies/enforcers/expert_review_required.py +1 -4
  147. package/templates/hooks/__pycache__/deliver_autoroute.cpython-312.pyc +0 -0
  148. package/tools/agents/scripts/__pycache__/toolcall_path_normalizer.cpython-312.pyc +0 -0
  149. package/tools/agents/scripts/anthropic_proxy.py +374 -16
  150. package/tools/agents/scripts/confidence_escalation.py +4 -2
  151. package/tools/agents/scripts/project_telemetry.py +1 -0
  152. package/tools/agents/scripts/tool_risk.py +1 -0
  153. package/tools/agents/scripts/tool_risk_calibrate.py +1 -0
  154. package/tools/agents/scripts/toolcall_path_normalizer.py +1 -0
  155. package/tools/agents/tests/test_anthropic_proxy_streaming.py +52 -1
  156. package/tools/agents/tests/test_confidence_escalation.py +3 -2
  157. package/tools/agents/tests/test_count_tokens_scale_per_session.py +126 -0
  158. package/tools/agents/tests/test_expert_review_pr_scope.py +10 -11
  159. package/tools/agents/tests/test_lockstep_escalation.py +324 -0
  160. package/tools/agents/tests/test_thinking_template_kwargs.py +10 -4
@@ -112,3 +112,271 @@ The llama.cpp env (`~/.config/uap/llama-server.env` →
112
112
  `config/llama-profiles/qwen38-27b-dflash2.env`) and the ik/DFlash2 binary are
113
113
  exactly as they were; the service was only `disable`d so it stops competing
114
114
  for VRAM and port 8080 on boot.
115
+
116
+ ## What's next: Qwen3.8-Flash-Next as the 27B replacement (2026-09-09)
117
+
118
+ Status: **evaluation in progress** — both serving paths are now benched at
119
+ 2.05bpw/3bpw class and the tool-call smoke test passes; the 4.05bpw quant is
120
+ downloaded but its bench is on hold. The GGUF stack is the live server on
121
+ `:8080` in the original config (the ≥1 GB VRAM tuning below was tried and
122
+ reverted — decode cost not worth the headroom). This section is the running
123
+ analysis and updates as measurements land.
124
+
125
+ ### The model
126
+
127
+ Qwen3.8-Flash-Next ("A Preview of the Qwen4 Architecture" per the GGUF
128
+ metadata) is a hybrid linear-attention MoE, a generation ahead of the dense
129
+ 27B:
130
+
131
+ - 48 layers; **gated-delta SSM layers with a full-attention layer every
132
+ 4th** (`full_attention_interval = 4`), so only 12 layers hold KV
133
+ - **512 experts per layer, 10 active + shared**; hidden 2560; card size
134
+ label `512x56B` (125B-A6B class)
135
+ - **MTP head + PLE trigram table built in** — the ngram embedding table
136
+ alone is 26.2 GB bf16 in the EXL3 checkpoints
137
+ - **Vision-capable** (the 27B is text-only)
138
+ - Native context **262144**
139
+
140
+ ### What changed on 2026-09-08 (joaosump's quant comparison)
141
+
142
+ [@joaosump's bench thread](https://x.com/joaosump/status/2097225621621338408)
143
+ (turboderp EXL3 quants, single RTX 3090):
144
+
145
+ - **4bpw KLD is excellent**, and both 4bpw and 5bpw are usable on a single
146
+ 3090 — so the 2bpw class is a speed experiment, not the serving quant.
147
+ - Thread corroboration: the **2bpw already sustains 2-hour agentic runs at
148
+ 67–68 t/s with working tool calling**; the earlier "2bpw breaks tool
149
+ calling" report traced to exllamav3 template parsing, not the quant —
150
+ consistent with what we saw wiring `qwen-sharp.jinja`.
151
+ - Caveat worth respecting (AIQuanting in-thread): KLD averages over every
152
+ token and most tokens are easy. The number that matters for code is
153
+ **top-token flips where the unquantized model was confident** — so the
154
+ 4bpw decision still needs our own quality bench, not just KLD.
155
+
156
+ ### Local state (verified 2026-09-09)
157
+
158
+ | Artifact | Path | Size | Status |
159
+ |---|---|---|---|
160
+ | GGUF UD-IQ3_XXS (~3bpw) + MTP sidecars | `~/models/flash-next/` | 82 GB + MTP | benched (below) |
161
+ | EXL3 2.05bpw_h4_ng4 (turboderp) | `~/models/flash-next-exl3/2.05bpw/` | 62.5 GB (26.2 GB is the PLE table) | benched + tool-call smoke test passed |
162
+ | EXL3 4.05bpw_h6_ng6 (turboderp) | `~/models/flash-next-exl3/4.05bpw/` | 101 GB | downloaded; bench on hold |
163
+ | Bench harness (`bench.py`, `bench_exl3.py`) | `~/dev/flash-next-bench/` | — | working |
164
+ | Serving kit (EXL3 copy) | `~/Qwen3.8-FlashNext-EXL3-kit/` | — | configured + patched (below) |
165
+
166
+ ### Measured: GGUF path (buun-llama-cpp 40262a4, VBR KV, MTP drafting)
167
+
168
+ Same probe style as the 27B numbers above (unique random prefix per run,
169
+ temperature 0, 128-token decode):
170
+
171
+ | prompt depth | prefill t/s | decode t/s |
172
+ |---|---|---|
173
+ | ~2k (cold MoE cache) | 178 | 21.6 → 46.7 |
174
+ | ~2k (warm) | 253–279 | 51.5–64.2 |
175
+ | ~32k | 231 | 54.1 |
176
+ | ~92k | 195–203 | 34.9 |
177
+
178
+ MTP draft acceptance 0.851 (mean len 2.70). Memory at 92k ctx: 7.4 GB VRAM
179
+ resident + 16.5 GB MoE expert cache on the card, 77.5 GB host RAM — this is
180
+ a **CPU-offload model on a 24 GB card**; the 5950X's 124 GB RAM is the
181
+ second tier. MoE cache hit rate 80%.
182
+
183
+ ### Measured: EXL3 path (exllamav3 1.4.8+cu128/torch 2.10, 2.05bpw, MTP)
184
+
185
+ Kit config: `--moe_cpu_split 288` (tail 288 of 512 experts per layer in
186
+ RAM), `--moe_cpu_threads 32`, `--ngram_ram` (the 26 GB PLE table streams
187
+ from disk per token without it), `--cache_quant 4`, 131072 ctx. Exact prompt
188
+ counts come from a local `serve_openai.py` patch that emits the OpenAI
189
+ `stream_options.include_usage` chunk (the streaming path previously dropped
190
+ `stream_options` and never sent usage).
191
+
192
+ | prompt depth | prompt tokens | prefill t/s | decode t/s |
193
+ |---|---|---|---|
194
+ | ~2k | 2514 | 641 | 18.1 |
195
+ | ~32k | 38808 | 1091 | 19.0 |
196
+ | ~92k | 108877 | 1036 | 18.2 |
197
+
198
+ (prompt sizes overshoot the targets — `bench_exl3.py` estimates ~4
199
+ chars/token without a tokenize endpoint, so read these as 2.5k/38.8k/108.9k.
200
+ Decode is flat across depths: with the hybrid arch only 12 layers hold KV,
201
+ and the CPU expert GEMM dominates at a constant per-token cost. A second
202
+ back-to-back run showed no warm-up effect — 14–19 t/s — unlike the GGUF
203
+ MoE heat cache.)
204
+
205
+ **Tool-calling smoke test (2.05bpw): passed** — `tool_choice: auto` produced
206
+ a well-formed `get_weather(city="Tokyo")` call with `finish_reason:
207
+ "tool_calls"`, consistent with the thread's resolution that the 2bpw
208
+ tool-call failures were template parsing, not the quant.
209
+
210
+ ### The honest comparison vs the 27B EXL3 stack
211
+
212
+ - **Decode: GGUF wins.** Warm GGUF runs 51–64 t/s at short ctx, 54 at 32k,
213
+ 35 at 92k; EXL3 2.05bpw is flat ~17–19 t/s. The buun fork's persistent MoE
214
+ heat cache (80% hit) is the difference; EXL3's dynamic placement did not
215
+ warm up on this workload.
216
+ - **Prefill: EXL3 wins, and it flips the deployment story.** 641–1091 t/s vs
217
+ GGUF's 180–280 — a 64k-token session turn prefills in **~60–75 s on EXL3**
218
+ vs 4–7 minutes on GGUF. The proxy heartbeat rails (#785, #787, #788) are
219
+ still required for the GGUF path; EXL3 keeps long turns comfortably inside
220
+ the ~242 s watchdog.
221
+ - **vs the 27B:** Flash Next decode on EXL3 (~18 t/s) is well under the 27B
222
+ EXL3 stack (~82 t/s warm, 41–51 deep); GGUF closes most of that gap when
223
+ warm. Flash Next's case is capability (newer, larger, vision), not speed.
224
+ - **Memory economics flip.** The 27B is ~21 GB VRAM and negligible RAM;
225
+ Flash Next is ~8 GB VRAM + ~78 GB RAM (GGUF) or GPU/CPU expert split
226
+ (EXL3). Combined they exceed the card, so this is a **replacement, not a
227
+ side-by-side** — the 27B EXL3 service stays down while Flash Next is under
228
+ test.
229
+
230
+ ### Tuned GGUF serving config (2026-09-09, ≥1 GB VRAM freed — REVERTED)
231
+
232
+ **Reverted same day:** the decode cost (~27–37 t/s under churn vs the
233
+ 51–64 peak) was not worth the headroom; the live server runs the original
234
+ config below. Kept as a record of the only safe way to free VRAM on this
235
+ stack.
236
+
237
+ `GGML_CUDA_MOE_CACHE_RESERVE_MB=3072` + `--no-logits-all`, everything else
238
+ as benched, gave **1763 MiB free at 92k ctx** (vs 141 MiB stock), zero OOM
239
+ across the full 2k/32k/92k ladder, prefill unchanged (199–287 t/s).
240
+
241
+ Live config — **systemd, not manual**. Enablement follows the chosen
242
+ boot backend (2026-09-09: `uap-exl3-server` + proxy enabled for boot —
243
+ the pre-Flash-Next behavior — while Flash Next keeps running until the
244
+ next switch/reboot; `~/.config/uap/model-switch.sh flash|exl3|status` is
245
+ the switcher and re-aligns enablement):
246
+
247
+ - `uap-flashnext-server.service` — the GGUF server on `:8080`. Its
248
+ `ExecStart` is the source of truth; key deltas from the bench config:
249
+ `-ub 2048 --fit-target 4096 --fit on --alias qwen38-flash-next
250
+ --reasoning-format auto`. The `-ub 2048` roughly doubles prefill
251
+ (**627 t/s measured at 2k** — a 64k-token turn is ~105 s, inside the
252
+ ~242 s client watchdog that the ub-512 config livelocked against) and
253
+ `--fit-target 4096` holds 4 GiB back from the MoE cache so the larger
254
+ prefill compute buffers fit. `Conflicts=` with `uap-exl3-server` /
255
+ `uap-llama-server` enforces backend mutual exclusion.
256
+ - `uap-anthropic-proxy.service` — the Anthropic-protocol proxy on `:4000`
257
+ (upstream `http://127.0.0.1:8080/v1`, env in
258
+ `~/.config/uap/anthropic-proxy.env`, local-only routing pin intact).
259
+ End-to-end verified 2026-09-09: `POST :4000/v1/messages` →
260
+ `qwen38-flash-next` → correct response + usage.
261
+
262
+ Bench reconstruction note: the earlier bench runs used `-ub 512` without
263
+ `--fit-target`; that config's prefill (180–280 t/s) is why the proxy
264
+ heartbeat rails (#785, #787, #788) were load-bearing. With the unit's
265
+ `-ub 2048` they become belt-and-braces rather than required.
266
+
267
+ **Lesson (two failed attempts before this worked):** do **not** cap the
268
+ MoE cache with `--moe-cache N` / `on` — explicit budgets are non-evictive,
269
+ so the deep-context transients (CUDA graph capture, ~1.2 GB compute buffer,
270
+ VBR side-stream transcoding) OOM the server at 74k+ tokens. `auto` mode is
271
+ evictive and survives; raising its reserve is the only safe lever.
272
+ `--vbr-vram-budget 3G` was also tried and is unnecessary — VBR's KV stays
273
+ ~1.5 GB at 131k on this hybrid arch (only 12 layers hold KV). `-ub 256`
274
+ halves the compute spike but costs ~40% prefill; not worth it once the
275
+ reserve handles it.
276
+
277
+ ### Kit deltas (FlashNext kit, outside the repo — reapply if re-cloned)
278
+
279
+ 1. `start.sh`: passes `--moe_cpu_split $MOE_CPU_SPLIT`,
280
+ `--moe_cpu_threads $MOE_CPU_THREADS`, `--ngram_ram` from `.env` through
281
+ to `serve_openai.py` (long forms only — argparse eats `-mcs 288` as
282
+ `-m cs`). Without `--moe_cpu_split` the autosplit dies with
283
+ `Insufficient VRAM in split for model and cache`; the 101 GB 4.05bpw
284
+ quant needs ~400 (vs 288 for 2.05bpw).
285
+ 2. `tools/serve_openai.py`: emits the `stream_options.include_usage` final
286
+ chunk with real token counts, `parse_request` now carries
287
+ `stream_options`, and `/v1/models` reports the checkpoint dir name
288
+ instead of a hardcoded 27B id.
289
+ 3. `.env`: `CACHE_QUANT=4`, `MOE_CPU_SPLIT=288`, `MOE_CPU_THREADS=32`,
290
+ `NGRAM_RAM=1`, 131072 ctx, port 8080. The venv is upstream exllamav3
291
+ 1.4.8+cu128 on torch 2.10 (not the 27B kit's MiaAI fork 1.4.2 / cu124
292
+ stack) — no triton shim needed here.
293
+
294
+ ### Plan
295
+
296
+ 1. ~~Download 4.05bpw; configure the FlashNext-EXL3-kit~~ — done
297
+ (2026-09-09), including the CPU-split offload wiring the 2.05bpw bench
298
+ needed. 4.05bpw bench is **on hold**; when it resumes it needs
299
+ `MOE_CPU_SPLIT≈400` (GPU-resident expert share scales with bpw).
300
+ 2. ~~Bench 2.05bpw EXL3 at 2k/32k/92k~~ — done (table above); tool-call
301
+ smoke test passed.
302
+ 3. Quality gate before any switch: the full tool-call suite plus a real
303
+ `uap deliver` session — per the KLD caveat, top-token-flip behavior on
304
+ code is the deciding metric, not averages. Open question for the serving
305
+ decision: GGUF's warm decode (51–64 t/s) vs EXL3's prefill (4–5x
306
+ faster) — the right answer may be workload-dependent (long-prefill agent
307
+ loops favor EXL3; long-generation favors GGUF).
308
+ 4. The 27B EXL3 stack stays production until (3) passes; rollback stays as
309
+ documented above.
310
+
311
+ ## Signal 3.8 27B — ACTIVE backend since 2026-09-12
312
+
313
+ **Activated 2026-09-12** (operator confirmed Flash Next work done) via
314
+ `model-switch.sh signal`: `uap-signal-server` is now the enabled boot backend
315
+ (+ proxy); `uap-exl3-server` and `uap-flashnext-server` are disabled.
316
+
317
+ **Measured on this box** (AP-IQ4_XS, buun fork, `-ub 2048 --fit-target 4096`,
318
+ q4 KV, 131k ctx; tuned 2026-09-12 with `--cache-ram 16384 -t 16` from the
319
+ proven dflash2 profile — prompt-cache reuse across agent-loop turns —
320
+ plus `--ctx-checkpoints 2`: each checkpoint pins ~150 MiB of VRAM on this
321
+ dense model, so the old profile's 64 is not viable here. Server footprint
322
+ is a steady ~22.0 GiB; remaining "free VRAM" variance (150–900 MiB) is the
323
+ desktop session (gnome-shell/firefox/warp ≈ 1.4–2 GiB), not the server.
324
+ Bigger structural levers if ever needed: `-c 65536` (−3.5 GiB), drop
325
+ `--mmproj` (−0.9 GiB), `-ngl` trim (−0.2 GiB/layer)):
326
+
327
+ | config | 2k prefill/decode | 32k | 92k | VRAM @92k |
328
+ | --- | --- | --- | --- | --- |
329
+ | `--spec-type draft-mtp` (native head) | 780 / 36.3 | 727 / 20.1 | 557 / 13.3 | 21.2 GiB |
330
+ | **`--spec-type draft-dflash` (DFlash2 draft)** | **871 / 45.6** | **731 / 31.3** | **597 / 30.0** | 22.7 GiB |
331
+
332
+ DFlash2 (the draft trained for base Qwen3.8-27B) transfers fine to Signal
333
+ (acceptance 0.60–0.80) and beats the native MTP head at every depth — 2.3x
334
+ at 92k — so the unit runs draft-dflash. Tool-call smoke test passed
335
+ (`get_weather(city="Tokyo")`), proxy end-to-end verified on :4000.
336
+
337
+ **Honest verdict vs the EXL3 27B stack:** raw decode still loses (45.6 vs ~82
338
+ warm; 30 vs 41–51 deep). But Signal's −57% output tokens flip the wall-clock:
339
+ median general answer ≈ 104 tok @ 45.6 = **2.3 s** vs 243 tok @ 82 = 3.0 s;
340
+ at depth 104 @ 30 = **3.5 s** vs 243 @ 46 ≈ 5.3 s. Less proxy pressure and
341
+ smaller context footprint come free. Risks stand: day-one model,
342
+ self-reported quality numbers, GGUF-only.
343
+
344
+ ### Signal background (staged 2026-09-10)
345
+
346
+ [@laurent_zw's announcement](https://x.com/laurent_zw/status/2097813032671858809)
347
+ (AgentionAI): **Signal 3.8 27B**, a self-distillation of Qwen3.8-27B trained
348
+ on the base model's own answers under a "be direct" instruction. Claimed and
349
+ card-measured: **−57% answer tokens, −52% thinking tokens, <half the
350
+ wall-clock**, GSM8K parity (98.3% = base; thinking 95.0% vs 92.5%), MTP draft
351
+ acceptance up (prose 39→47%, JSON 72→94%). GGUF-only release
352
+ (`agentionai/Signal-3.8-27B-GGUF`, Apache-2.0) — no safetensors, so **no EXL3
353
+ path**; adopting it means llama.cpp, not exllamav3.
354
+
355
+ Verified from file headers/source: dense `qwen35` arch, **262144 native ctx**
356
+ (131072 is native, not stretched), MTP head embedded in the GGUF (the buun
357
+ fork's `--spec-type draft-mtp` detects native MTP layers — no sidecar),
358
+ vision encoder untouched (base `mmproj-BF16.gguf` shipped alongside).
359
+
360
+ **Fit vs the EXL3 27B stack:** raw decode likely loses (EXL3 ~82 t/s warm vs
361
+ est. ~60–75 with MTP on llama.cpp), but per-task wall-clock should win —
362
+ output volume roughly halves, which dominates. VRAM at 131k: IQ4_XS 13.27 GiB
363
+ + q4 KV ~4.3 + compute ~1.5 ≈ **19 GiB** (comfortable). Risks: day-old,
364
+ self-reported benchmarks, single-author tune, GGUF lock-in.
365
+
366
+ **Staged (not active):**
367
+
368
+ - Download: `AP-IQ4_XS` (13.27 GiB, max-headroom tier) + `mmproj-BF16.gguf`
369
+ → `~/models/signal-27b/`
370
+ - `uap-signal-server.service` — created, **disabled/inactive** on purpose.
371
+ Same buun-fork binary and `-ub 2048 --fit-target 4096 --fit on` pattern as
372
+ `uap-flashnext-server`, plus `-ctk q4_0 -ctv q4_0` (131k KV at f16 would
373
+ cost ~17 GiB), `--spec-type draft-mtp`, card sampling defaults
374
+ (0.7/0.95/20/0), `Conflicts=` with all three other :8080 backends.
375
+ - `~/.config/uap/model-switch.sh` extended: `signal` target + `status` now
376
+ covers all three model units. Activation (done 2026-09-12):
377
+ `model-switch.sh signal` (stops the others, enables signal for boot).
378
+
379
+ **Activation checklist (all passed 2026-09-12):** draft attach confirmed —
380
+ and upgraded: draft-mtp worked but draft-dflash measured faster, so the unit
381
+ switched drafts; tool-call smoke test ✓; proxy end-to-end ✓; 2k/32k/92k
382
+ bench ladder ✓ (table above).
@@ -0,0 +1,67 @@
1
+ # Harness/Loop/Graph master-architecture uplift — 2026-09-24
2
+
3
+ **Source:** [@marfinxx, 2026-07-27](https://x.com/marfinxx/status/2081687570488954915)
4
+ — "Harness Engineering, Loop Engineering, and Graph Engineering are not
5
+ competing ideas; they are the three structural layers of a single production
6
+ system." Five-stage master architecture: sandbox init → parallel graph fan-out →
7
+ local evidence-gated retry loops → harness state hashing / token dedup →
8
+ adversarial red-team gate → verified PR.
9
+
10
+ **Relation to prior work:** the 2026-07-31 harness-engineering uplift
11
+ (`harness-engineering-uplift-2026-07-31.md`) covered the ETCLOVG/harness side
12
+ (edit-tool ladder, evidence corpus, self-harness inversion, active memory). This
13
+ plan covers the marfinxx post's distinct emphases: the **graph layer as the
14
+ default topology**, **state-hash token dedup**, the **adversarial gate as a
15
+ mandatory pipeline stage**, and **one entry point composing all five stages**.
16
+
17
+ ## UAP scored against the three layers (2026-09-24)
18
+
19
+ | Layer | Post's requirement | UAP today | Verdict |
20
+ |---|---|---|---|
21
+ | Harness | spec file, sandbox, least-privilege, memory outside model | CLAUDE.md spec, worktree gate, `sandbox.ts`/`sanitized-env.ts`, Qdrant + active-reconstruction memory, policy enforcers | Strong |
22
+ | Loop | evidence-gated stops, budget caps, attempt limits | `verifier-ladder.ts`, `execution-gate.ts`, `convergence-loop.ts`, completion gates, proxy repeat-guard/attractor detection, `capacity-policy.json` | Strong — ahead of the post |
23
+ | Graph | fan-out by default, specialized sub-agents, sync/approval gates | `task-orchestrator.ts` wave-barrier parallel dispatch exists but **defaults to `concurrency: 1`**, opt-in via `deliver.parallelTasks` | Partial — weakest layer |
24
+
25
+ Gaps vs the five stages:
26
+
27
+ 1. **Stage 2** — fan-out is opt-in, not the default topology.
28
+ 2. **Stage 4** — no content-hash dedup serving zero-token cached reads across
29
+ turns; only in-process `ReadCache` notes and proxy repeat detection.
30
+ 3. **Stage 5** — adversarial machinery exists (`test-oracle-additive.ts`,
31
+ `critic.ts`, `deep-security-review`) but no default pre-PR node that writes
32
+ edge-case tests to break the patch.
33
+ 4. **No single entry point** composing the five stages ("one prompt → verified
34
+ PR").
35
+ 5. **No measured intern-vs-master number** — the K3 paired validation
36
+ (`k3-uap-uplift-validation.md`) was planned but never executed.
37
+
38
+ ## Selected options (user-approved 2026-09-24)
39
+
40
+ | # | Option | Layer | Status |
41
+ |---|---|---|---|
42
+ | E | K3 paired bench Phase 0 | Evaluation | Adapter shipped (`benchmarks/terminal_bench/uap_droid_agent.py` + `uap-droid-setup.sh.j2`); **paid smoke blocked on missing keys** (`UAP_TB_KIMI_API_KEY`/`UAP_TB_OPENROUTER_API_KEY`/`UAP_TB_FACTORY_API_KEY`) |
43
+ | A | Graph default flip: parallel fan-out default in `task-orchestrator` | Graph | in progress |
44
+ | B | Harness state-hash read dedup (extend `ReadCache`, content-hash keyed, write-invalidated) | Harness | in progress |
45
+ | C | Adversarial red-team gate stage before PR | Graph/Loop | pending |
46
+ | D | Master pipeline entry point composing stages | All | pending (after A–C) |
47
+ | F | Docs positioning | — | not selected |
48
+
49
+ ## Constraints
50
+
51
+ 1. Nothing accepted on reasoning alone: behavioral defaults (A, B) ship behind
52
+ measurements or with an escape hatch, per the harness-coupling warning in the
53
+ 2026-07-31 plan.
54
+ 2. Parallelism flip must preserve the safety property the `concurrency: 1`
55
+ default protected (shared-tree mutation); parallel only where isolation is
56
+ in place.
57
+ 3. Dedup must never serve stale content; write paths invalidate.
58
+ 4. The adversarial gate composes existing machinery rather than adding a new
59
+ model call where a deterministic check suffices (post's anti-pattern #4:
60
+ don't force deterministic work into models).
61
+
62
+ ## Validation
63
+
64
+ - Per-change: build + targeted vitest/pytest.
65
+ - Pre-merge: full `npm test`, `tsc --noEmit`, parallel review protocol
66
+ (code-quality / security / architecture) with `uap review prepass`.
67
+ - Uplift claim: only after the E bench runs; no forecast deltas.
@@ -91,6 +91,12 @@ Top level: `version`, `project`, `memory`, `worktree`, `costOptimization`,
91
91
  | `UAP_AGENT_ID` | Agent id for MCP execute | `mcp-<pid>` |
92
92
  | `UAP_MAX_PARALLEL` | Override max parallel workers | auto |
93
93
  | `UAP_PARALLEL` | `false` disables parallelism | enabled |
94
+ | `UAP_DELIVER_PARALLEL_TASKS` | Override `deliver.parallelTasks`: `1` forces sequential task dispatch everywhere (escape hatch); `2`–`8` retunes the fan-out cap. Set-but-invalid fails safe to sequential. | unset (config wins) |
95
+ | `UAP_DELIVER_STATE_HASH` | State-hash read dedup in the deliver executor: a within-turn re-read of a file window whose sha256 is unchanged serves a compact reference instead of full content (token saving); writes/edits invalidate, external edits are caught by re-hashing on read. `0` disables. Note: the compact reference carries a 48-bit sha256 prefix plus the exact byte count into run telemetry — negligible for source trees, relevant if runs read secret-bearing files. | on |
96
+ | `UAP_DELIVER_STATE_HASH_MIN_BYTES` | Size floor below which a repeated read is cheaper to serve in full than as a reference. | `1024` |
97
+ | `UAP_DELIVER_ADVERSARIAL_GATE` | Adversarial red-team gate: after a deliver run converges, a bounded skeptic pass authors edge-case tests against the patch (append-only oracle channel); a breach routes back into the loop as ordinary gate feedback. `0`/`off`/`false` disables; a positive integer retunes the round budget (cap 4). Set-but-invalid fails safe to ON. Residual risk: authored adversarial tests execute with host privileges (env-stripped only — file-based credentials such as `~/.aws` are still reachable), and repo content is a prompt-injection channel into the authoring model; use `uap sandbox` containment for untrusted repos. | on (≤2 rounds) |
98
+ | `UAP_DELIVER_CRITERIA_LINT` | Plan-time criteria lint: planner/split-emitted acceptance criteria that assert runtime BEHAVIOR without a machine-checkable anchor (e.g. "the user can rotate faces and the stickers update") are rewritten in place with an explicit executable-evidence clause (a deep `.uap/user-paths.json` journey or a test/script), so "page loads without errors" can no longer satisfy them. `0`/`off`/`false` disables. | on |
99
+ | `UAP_DELIVER_EVIDENCE_GATE` | Anti-vacuous delivery + over-claim metric: when the acceptance judge (or churn breaker) says PASS, audit the executable evidence that ran this turn — a trusted user-paths pass with ≥1 deep journey, a non-skipped interaction-gate pass, or (secondary mode) a green objective ladder. A rendered web page with none of those is REFUSED with feedback demanding a deep journey, forcing another turn while budget remains. Every audited pass is appended to `.uap/delivery-evidence.jsonl` (a `sufficient:false` row is a caught over-claim; bench harnesses cross-join it with external verify results). Non-web deliverables (no entry page, no manifest) stay judge-gated. `0`/`off`/`false` disables. | on |
94
100
 
95
101
  ### `.uap.json` `deliver` section
96
102
 
@@ -98,7 +104,10 @@ Top level: `version`, `project`, `memory`, `worktree`, `costOptimization`,
98
104
  |---|---|---|
99
105
  | `deliver.orchestrate` | Blackboard orchestration for decomposed missions (`"on"`/`"off"`) | `"on"` (preflight seeds it) |
100
106
  | `deliver.epics` | Epic controller outer loop (`"on"`/`"off"`) | `"on"` (preflight seeds it) |
101
- | `deliver.parallelTasks` | Worktree-isolated parallel dispatch: independent READY orchestrator tasks run concurrently, each convergence loop + its gates in a detached git worktree seeded with the mission's current state; deltas merge back serially, and a merge conflict fails the task into the minimal-repair retry. Clamped to 1–8. **Config-only by design — no env override** (an exported variable must never silently parallelize every run). | `1` (sequential) |
107
+ | `deliver.parallelTasks` | Worktree-isolated parallel dispatch: independent READY orchestrator tasks run concurrently, each convergence loop + its gates in a detached git worktree seeded with the mission's current state; deltas merge back serially, and a merge conflict fails the task into the minimal-repair retry. Clamped to 1–8. **Parallel is the default** — an unset key resolves to 4, capped per wave at the number of independent READY tasks. Parallelism is conditional on worktree isolation: outside a git repo (or with an unborn HEAD) the run stays sequential and logs why. Set `1` (or `UAP_DELIVER_PARALLEL_TASKS=1`) to force sequential execution. | `4` (parallel, worktree-isolated) |
108
+ | `deliver.adversarialGate` | Adversarial red-team gate before a converged run is accepted (`false`/`0`/`"off"` disables; a positive integer retunes the round budget, cap 4). Overridden by `UAP_DELIVER_ADVERSARIAL_GATE`. | on (≤2 rounds) |
109
+ | `deliver.criteriaLint` | Plan-time lint of planner/split-emitted acceptance criteria; behavioral criteria gain an executable-evidence clause. Overridden by `UAP_DELIVER_CRITERIA_LINT`. | on |
110
+ | `deliver.evidenceGate` | Anti-vacuous delivery gate + over-claim metric stream (`.uap/delivery-evidence.jsonl`). Overridden by `UAP_DELIVER_EVIDENCE_GATE`. | on |
102
111
  | `deliver.autoSizeEpics` | Context auto-size for epic sessions (`false`/`"off"` disables) | enabled |
103
112
  | `UAP_BENCHMARK_MODE` | `true` enables benchmark template mode | off |
104
113
  | `UAP_BENCHMARK_PARALLEL` | Parallel model count in benchmarks | — |
@@ -795,6 +795,20 @@ When the model self-reports "stuck" but keeps repeating the same failing tool, r
795
795
 
796
796
  **Recommendation:** Keep on for local models; harmless for cloud models (rarely triggers).
797
797
 
798
+ ### `PROXY_LOCKSTEP_BREAK`
799
+
800
+ | | |
801
+ |---|---|
802
+ | **Where** | `.uap/proxy.env` |
803
+ | **Type** | boolean (+ `PROXY_LOCKSTEP_PIVOT_AT` / `PROXY_LOCKSTEP_HARD_AT` numbers) |
804
+ | **Default** | `true` (pivot at streak 2, hard stop at streak 4) |
805
+
806
+ When the *identical* tool call fails with the *identical* error, escalates decisively: pivot directive → final warning → hard-fail the session with a 400, recording each tier to the loop-incident ledger (`UAP_LOOP_INCIDENTS`, default `~/.config/uap/loop-incidents.jsonl`). Both directives are always given before the stop, so the stop lands at `max(HARD_AT, PIVOT_AT + 2)` — never earlier. `uap loops` lists the ledger and prints a ready `uap ideate`/`uap deliver` handoff for the broken loop. A fresh human user turn re-arms the guard.
807
+
808
+ **Dependency:** the streaks lockstep reads are fed by the ERROR-LOOP and DOUBLING-DOWN trackers — `PROXY_ERROR_LOOP=off` or `PROXY_DOUBLING_BREAK=off` silently disarms lockstep too. `PIVOT_AT=0` disables the guard; `HARD_AT=0` disables only the hard stop.
809
+
810
+ **Recommendation:** Keep on — this is the guard that ends deterministic-failure loops in minutes instead of tens of wasted full-context turns.
811
+
798
812
  ### `PROXY_RECON_CONVERGENCE_THRESHOLD`
799
813
 
800
814
  | | |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@miller-tech/uap",
3
- "version": "2.11.1",
3
+ "version": "2.16.4",
4
4
  "description": "Autonomous AI agent memory system with CLAUDE.md protocol enforcement",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -21,7 +21,7 @@
21
21
  "start": "node dist/bin/cli.js",
22
22
  "test": "vitest",
23
23
  "test:ci": "vitest run",
24
- "test:enforcers": "UAP_PROXY_ENV_AUTOLOAD=0 python3 -m unittest tools.agents.tests.test_enforcement_self_protect tools.agents.tests.test_conditional_destructive_verbs tools.agents.tests.test_live_deliver_kill tools.agents.tests.test_schema_diff_gate tools.agents.tests.test_schema_diff_inline tools.agents.tests.test_stream_telemetry tools.agents.tests.test_project_telemetry_events tools.agents.tests.test_workdir_scope_enforcer tools.agents.tests.test_gate_evidence tools.agents.tests.test_repeat_call_guard tools.agents.tests.test_repeat_guard tools.agents.tests.test_gate_integrity tools.agents.tests.test_gate_failclosed_indirection tools.agents.tests.test_gate_failclosed_schema_diff tools.agents.tests.test_expert_review_pr_scope tools.agents.tests.test_path_containment tools.agents.tests.test_path_normalizer_hardened tools.agents.tests.test_sandbox_tool_strip tools.agents.tests.test_proxy_env_loader tools.agents.tests.test_stream_required_tool tools.agents.tests.test_tool_call_wrapper_profiles tools.agents.tests.test_tool_convert_cache tools.agents.tests.test_doubling_break tools.agents.tests.test_error_loop_ignores_correctives tools.agents.tests.test_anthropic_proxy_tool_arg_types tools.agents.tests.test_anthropic_sse_schema tools.agents.tests.test_attractor_detection tools.agents.tests.test_client_disconnect tools.agents.tests.test_confidence_escalation tools.agents.tests.test_coordination_ban tools.agents.tests.test_coordination_early_ban tools.agents.tests.test_cycle_break_exploration tools.agents.tests.test_deferral_break tools.agents.tests.test_deliver_autoroute tools.agents.tests.test_delivery_enforcement_all_langs tools.agents.tests.test_delivery_enforcement_exemptions tools.agents.tests.test_delivery_enforcement_filepath tools.agents.tests.test_delivery_enforcement_write_complexity tools.agents.tests.test_fastpath_config tools.agents.tests.test_delivery_enforcement_web_and_bash tools.agents.tests.test_disconnect_watcher tools.agents.tests.test_empty_maxtokens_recovery tools.agents.tests.test_empty_tool_loop_break tools.agents.tests.test_enforcer_escape_hatches tools.agents.tests.test_error_loop_break tools.agents.tests.test_finalize_suppression tools.agents.tests.test_malformed_unclosed_think tools.agents.tests.test_mandate_beats_recon tools.agents.tests.test_mandate_deliver tools.agents.tests.test_overflow_truncate_count_tokens tools.agents.tests.test_passthrough_oauth tools.agents.tests.test_project_telemetry tools.agents.tests.test_proxy_auth_headers tools.agents.tests.test_prune_preserve_force_write tools.agents.tests.test_recon_deliver_gate tools.agents.tests.test_session_admission tools.agents.tests.test_stream_heartbeat tools.agents.tests.test_stuck_break_reattach tools.agents.tests.test_stuck_break_hard tools.agents.tests.test_turn_count_breaker_periodic tools.agents.tests.test_upstream_chokepoint tools.agents.tests.test_vision_passthrough tools.agents.tests.test_worktree_required tools.agents.tests.test_enforcer_suite_coverage tools.agents.tests.test_validate_plan_gate tools.agents.tests.test_validate_plan_inside_project tools.agents.tests.test_anthropic_proxy_streaming tools.agents.tests.test_non_stream_resp_log tools.agents.tests.test_delivery_enforcement_worktree tools.agents.tests.test_output_token_ceilings tools.agents.tests.test_tool_narrowing_core tools.agents.tests.test_models_context_window tools.agents.tests.test_thinking_template_kwargs tools.agents.tests.test_cycle_break_wait_poll tools.agents.tests.test_upstream_model_aliases tools.agents.tests.test_stream_thinking_deltas tools.agents.tests.test_verbatim_compact tools.agents.tests.test_tool_risk",
24
+ "test:enforcers": "UAP_PROXY_ENV_AUTOLOAD=0 python3 -m unittest tools.agents.tests.test_enforcement_self_protect tools.agents.tests.test_conditional_destructive_verbs tools.agents.tests.test_live_deliver_kill tools.agents.tests.test_schema_diff_gate tools.agents.tests.test_schema_diff_inline tools.agents.tests.test_stream_telemetry tools.agents.tests.test_project_telemetry_events tools.agents.tests.test_workdir_scope_enforcer tools.agents.tests.test_gate_evidence tools.agents.tests.test_repeat_call_guard tools.agents.tests.test_repeat_guard tools.agents.tests.test_gate_integrity tools.agents.tests.test_gate_failclosed_indirection tools.agents.tests.test_gate_failclosed_schema_diff tools.agents.tests.test_expert_review_pr_scope tools.agents.tests.test_path_containment tools.agents.tests.test_path_normalizer_hardened tools.agents.tests.test_sandbox_tool_strip tools.agents.tests.test_proxy_env_loader tools.agents.tests.test_stream_required_tool tools.agents.tests.test_tool_call_wrapper_profiles tools.agents.tests.test_tool_convert_cache tools.agents.tests.test_doubling_break tools.agents.tests.test_error_loop_ignores_correctives tools.agents.tests.test_anthropic_proxy_tool_arg_types tools.agents.tests.test_anthropic_sse_schema tools.agents.tests.test_attractor_detection tools.agents.tests.test_client_disconnect tools.agents.tests.test_confidence_escalation tools.agents.tests.test_coordination_ban tools.agents.tests.test_coordination_early_ban tools.agents.tests.test_cycle_break_exploration tools.agents.tests.test_deferral_break tools.agents.tests.test_deliver_autoroute tools.agents.tests.test_delivery_enforcement_all_langs tools.agents.tests.test_delivery_enforcement_exemptions tools.agents.tests.test_delivery_enforcement_filepath tools.agents.tests.test_delivery_enforcement_write_complexity tools.agents.tests.test_fastpath_config tools.agents.tests.test_delivery_enforcement_web_and_bash tools.agents.tests.test_disconnect_watcher tools.agents.tests.test_empty_maxtokens_recovery tools.agents.tests.test_empty_tool_loop_break tools.agents.tests.test_enforcer_escape_hatches tools.agents.tests.test_error_loop_break tools.agents.tests.test_finalize_suppression tools.agents.tests.test_malformed_unclosed_think tools.agents.tests.test_mandate_beats_recon tools.agents.tests.test_mandate_deliver tools.agents.tests.test_overflow_truncate_count_tokens tools.agents.tests.test_count_tokens_scale_per_session tools.agents.tests.test_passthrough_oauth tools.agents.tests.test_project_telemetry tools.agents.tests.test_proxy_auth_headers tools.agents.tests.test_prune_preserve_force_write tools.agents.tests.test_recon_deliver_gate tools.agents.tests.test_session_admission tools.agents.tests.test_stream_heartbeat tools.agents.tests.test_stuck_break_reattach tools.agents.tests.test_stuck_break_hard tools.agents.tests.test_turn_count_breaker_periodic tools.agents.tests.test_upstream_chokepoint tools.agents.tests.test_vision_passthrough tools.agents.tests.test_worktree_required tools.agents.tests.test_enforcer_suite_coverage tools.agents.tests.test_validate_plan_gate tools.agents.tests.test_validate_plan_inside_project tools.agents.tests.test_anthropic_proxy_streaming tools.agents.tests.test_non_stream_resp_log tools.agents.tests.test_delivery_enforcement_worktree tools.agents.tests.test_output_token_ceilings tools.agents.tests.test_tool_narrowing_core tools.agents.tests.test_models_context_window tools.agents.tests.test_thinking_template_kwargs tools.agents.tests.test_cycle_break_wait_poll tools.agents.tests.test_upstream_model_aliases tools.agents.tests.test_stream_thinking_deltas tools.agents.tests.test_verbatim_compact tools.agents.tests.test_tool_risk tools.agents.tests.test_lockstep_escalation",
25
25
  "test:coverage": "vitest --coverage",
26
26
  "bench": "vitest --config vitest.bench.config.ts",
27
27
  "eval:routing": "tsx scripts/eval-routing.ts",
@@ -82,11 +82,17 @@ llama_upstream_is_chat_server() {
82
82
  # PATH 2 — any other OpenAI-compatible engine.
83
83
  #
84
84
  # Requiring /props made this check llama.cpp-SPECIFIC, and it rejected the
85
- # engine actually serving this host. Measured 2026-08-19: the box runs
85
+ # engine actually serving this host. Measured 2026-08-19: the box then ran
86
86
  # ninfer-serve, which serves /health and /v1/models but NO /props, so the live
87
87
  # server on the documented default port was refused, discovery yielded
88
88
  # nothing, the dead pin stood, and every local completion returned 529.
89
89
  #
90
+ # (2026-09-21: that host is back on llama.cpp and /props answers again, so
91
+ # this particular engine no longer triggers it. The check stays capability-
92
+ # based rather than endpoint-based on purpose — the point is not which
93
+ # engine is running today, it is that requiring a vendor-specific endpoint
94
+ # makes discovery reject any other one.)
95
+ #
90
96
  # The trust model asks for "chat-capable, and not the embedding server". That
91
97
  # is a CAPABILITY question, and the direct way to answer it is to ask for a
92
98
  # chat completion: an embedding-only server has no such route, and a decoy
@@ -64,10 +64,7 @@ GH_API_SHIP_RE = re.compile(
64
64
  )
65
65
  GIT_VALUE_OPTIONS = frozenset({"-C", "-c", "--git-dir", "--work-tree", "--namespace"})
66
66
  WRAPPER_VERBS = frozenset({
67
- # "rtk" stays even though UAP no longer integrates the rtk CLI: the binary
68
- # can still exist on operator machines, and without the unwrap, forms like
69
- # `rtk git -C /repo push` would slip past the ship gate (fail-open).
70
- "rtk", "env", "nohup", "sudo", "time", "command", "timeout", "stdbuf",
67
+ "env", "nohup", "sudo", "time", "command", "timeout", "stdbuf",
71
68
  })
72
69
  _SEGMENT_SPLIT = re.compile(r"(?:\|\||&&|[;\n|&])")
73
70
  _ENV_ASSIGN = re.compile(r"^[A-Za-z_][A-Za-z0-9_]*=\S*$")