@miller-tech/uap 2.21.3 → 2.36.1

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 (328) hide show
  1. package/README.md +22 -10
  2. package/config/model-profiles/qwen38-coder390.json +46 -0
  3. package/config/model-profiles/qwen38.json +3 -2
  4. package/config/model-registry.json +110 -0
  5. package/dist/.tsbuildinfo +1 -1
  6. package/dist/benchmarks/paired/types.d.ts +2 -2
  7. package/dist/bin/cli.js +315 -20
  8. package/dist/bin/cli.js.map +1 -1
  9. package/dist/cli/attention.d.ts +6 -0
  10. package/dist/cli/attention.d.ts.map +1 -0
  11. package/dist/cli/attention.js +115 -0
  12. package/dist/cli/attention.js.map +1 -0
  13. package/dist/cli/bench-report.d.ts +82 -0
  14. package/dist/cli/bench-report.d.ts.map +1 -0
  15. package/dist/cli/bench-report.js +237 -0
  16. package/dist/cli/bench-report.js.map +1 -0
  17. package/dist/cli/clients.d.ts +6 -0
  18. package/dist/cli/clients.d.ts.map +1 -0
  19. package/dist/cli/clients.js +142 -0
  20. package/dist/cli/clients.js.map +1 -0
  21. package/dist/cli/dashboard-grants.d.ts +26 -0
  22. package/dist/cli/dashboard-grants.d.ts.map +1 -0
  23. package/dist/cli/dashboard-grants.js +69 -0
  24. package/dist/cli/dashboard-grants.js.map +1 -0
  25. package/dist/cli/dashboard-pace.d.ts +31 -0
  26. package/dist/cli/dashboard-pace.d.ts.map +1 -0
  27. package/dist/cli/dashboard-pace.js +42 -0
  28. package/dist/cli/dashboard-pace.js.map +1 -0
  29. package/dist/cli/dashboard-session.d.ts +25 -0
  30. package/dist/cli/dashboard-session.d.ts.map +1 -0
  31. package/dist/cli/dashboard-session.js +814 -0
  32. package/dist/cli/dashboard-session.js.map +1 -0
  33. package/dist/cli/dashboard-types.d.ts +18 -0
  34. package/dist/cli/dashboard-types.d.ts.map +1 -0
  35. package/dist/cli/dashboard-types.js +9 -0
  36. package/dist/cli/dashboard-types.js.map +1 -0
  37. package/dist/cli/dashboard.d.ts +2 -18
  38. package/dist/cli/dashboard.d.ts.map +1 -1
  39. package/dist/cli/dashboard.js +43 -793
  40. package/dist/cli/dashboard.js.map +1 -1
  41. package/dist/cli/deliver.d.ts +35 -0
  42. package/dist/cli/deliver.d.ts.map +1 -1
  43. package/dist/cli/deliver.js +93 -9
  44. package/dist/cli/deliver.js.map +1 -1
  45. package/dist/cli/diff.d.ts +85 -0
  46. package/dist/cli/diff.d.ts.map +1 -0
  47. package/dist/cli/diff.js +293 -0
  48. package/dist/cli/diff.js.map +1 -0
  49. package/dist/cli/eta.d.ts +35 -0
  50. package/dist/cli/eta.d.ts.map +1 -0
  51. package/dist/cli/eta.js +101 -0
  52. package/dist/cli/eta.js.map +1 -0
  53. package/dist/cli/handsfree.d.ts +7 -0
  54. package/dist/cli/handsfree.d.ts.map +1 -1
  55. package/dist/cli/handsfree.js +27 -0
  56. package/dist/cli/handsfree.js.map +1 -1
  57. package/dist/cli/hooks.d.ts.map +1 -1
  58. package/dist/cli/hooks.js +126 -5
  59. package/dist/cli/hooks.js.map +1 -1
  60. package/dist/cli/loops.d.ts +24 -5
  61. package/dist/cli/loops.d.ts.map +1 -1
  62. package/dist/cli/loops.js +92 -12
  63. package/dist/cli/loops.js.map +1 -1
  64. package/dist/cli/models.d.ts +62 -0
  65. package/dist/cli/models.d.ts.map +1 -0
  66. package/dist/cli/models.js +567 -0
  67. package/dist/cli/models.js.map +1 -0
  68. package/dist/cli/plan.d.ts +9 -0
  69. package/dist/cli/plan.d.ts.map +1 -1
  70. package/dist/cli/plan.js +57 -4
  71. package/dist/cli/plan.js.map +1 -1
  72. package/dist/cli/proxy-relay.d.ts +55 -0
  73. package/dist/cli/proxy-relay.d.ts.map +1 -0
  74. package/dist/cli/proxy-relay.js +116 -0
  75. package/dist/cli/proxy-relay.js.map +1 -0
  76. package/dist/cli/proxy.d.ts +4 -0
  77. package/dist/cli/proxy.d.ts.map +1 -1
  78. package/dist/cli/proxy.js +26 -1
  79. package/dist/cli/proxy.js.map +1 -1
  80. package/dist/cli/sandbox.d.ts +101 -4
  81. package/dist/cli/sandbox.d.ts.map +1 -1
  82. package/dist/cli/sandbox.js +393 -44
  83. package/dist/cli/sandbox.js.map +1 -1
  84. package/dist/cli/self.d.ts +13 -0
  85. package/dist/cli/self.d.ts.map +1 -0
  86. package/dist/cli/self.js +94 -0
  87. package/dist/cli/self.js.map +1 -0
  88. package/dist/cli/systemd-services.d.ts +2 -8
  89. package/dist/cli/systemd-services.d.ts.map +1 -1
  90. package/dist/cli/systemd-services.js +5 -20
  91. package/dist/cli/systemd-services.js.map +1 -1
  92. package/dist/cli/task.js +1 -1
  93. package/dist/cli/task.js.map +1 -1
  94. package/dist/cli/wizard-config.d.ts.map +1 -1
  95. package/dist/cli/wizard-config.js +31 -2
  96. package/dist/cli/wizard-config.js.map +1 -1
  97. package/dist/config/settings-registry.d.ts +1 -1
  98. package/dist/config/settings-registry.d.ts.map +1 -1
  99. package/dist/config/settings-registry.js +108 -0
  100. package/dist/config/settings-registry.js.map +1 -1
  101. package/dist/coordination/capability-router.js +2 -2
  102. package/dist/coordination/capability-router.js.map +1 -1
  103. package/dist/coordination/database.d.ts +13 -0
  104. package/dist/coordination/database.d.ts.map +1 -1
  105. package/dist/coordination/database.js +63 -7
  106. package/dist/coordination/database.js.map +1 -1
  107. package/dist/coordination/eta-inject.d.ts +32 -0
  108. package/dist/coordination/eta-inject.d.ts.map +1 -0
  109. package/dist/coordination/eta-inject.js +64 -0
  110. package/dist/coordination/eta-inject.js.map +1 -0
  111. package/dist/coordination/reactor.d.ts.map +1 -1
  112. package/dist/coordination/reactor.js +14 -0
  113. package/dist/coordination/reactor.js.map +1 -1
  114. package/dist/coordination/service.d.ts +18 -8
  115. package/dist/coordination/service.d.ts.map +1 -1
  116. package/dist/coordination/service.js +38 -28
  117. package/dist/coordination/service.js.map +1 -1
  118. package/dist/dashboard/client-registry.d.ts +163 -0
  119. package/dist/dashboard/client-registry.d.ts.map +1 -0
  120. package/dist/dashboard/client-registry.js +549 -0
  121. package/dist/dashboard/client-registry.js.map +1 -0
  122. package/dist/dashboard/controls.d.ts.map +1 -1
  123. package/dist/dashboard/controls.js +33 -4
  124. package/dist/dashboard/controls.js.map +1 -1
  125. package/dist/dashboard/data-seeder.d.ts +10 -7
  126. package/dist/dashboard/data-seeder.d.ts.map +1 -1
  127. package/dist/dashboard/data-seeder.js +31 -75
  128. package/dist/dashboard/data-seeder.js.map +1 -1
  129. package/dist/dashboard/data-service.d.ts +9 -0
  130. package/dist/dashboard/data-service.d.ts.map +1 -1
  131. package/dist/dashboard/data-service.js +32 -3
  132. package/dist/dashboard/data-service.js.map +1 -1
  133. package/dist/dashboard/placement-routes.d.ts +119 -0
  134. package/dist/dashboard/placement-routes.d.ts.map +1 -0
  135. package/dist/dashboard/placement-routes.js +331 -0
  136. package/dist/dashboard/placement-routes.js.map +1 -0
  137. package/dist/dashboard/server.d.ts.map +1 -1
  138. package/dist/dashboard/server.js +408 -2
  139. package/dist/dashboard/server.js.map +1 -1
  140. package/dist/delivery/attention.d.ts +130 -0
  141. package/dist/delivery/attention.d.ts.map +1 -0
  142. package/dist/delivery/attention.js +341 -0
  143. package/dist/delivery/attention.js.map +1 -0
  144. package/dist/delivery/decompose.d.ts +18 -0
  145. package/dist/delivery/decompose.d.ts.map +1 -1
  146. package/dist/delivery/decompose.js +22 -1
  147. package/dist/delivery/decompose.js.map +1 -1
  148. package/dist/delivery/eta-estimate.d.ts +111 -0
  149. package/dist/delivery/eta-estimate.d.ts.map +1 -0
  150. package/dist/delivery/eta-estimate.js +171 -0
  151. package/dist/delivery/eta-estimate.js.map +1 -0
  152. package/dist/delivery/eta.d.ts +23 -0
  153. package/dist/delivery/eta.d.ts.map +1 -0
  154. package/dist/delivery/eta.js +59 -0
  155. package/dist/delivery/eta.js.map +1 -0
  156. package/dist/delivery/orchestrated-mission.d.ts +10 -0
  157. package/dist/delivery/orchestrated-mission.d.ts.map +1 -1
  158. package/dist/delivery/orchestrated-mission.js +15 -1
  159. package/dist/delivery/orchestrated-mission.js.map +1 -1
  160. package/dist/delivery/plan-check.d.ts +7 -1
  161. package/dist/delivery/plan-check.d.ts.map +1 -1
  162. package/dist/delivery/plan-check.js +23 -2
  163. package/dist/delivery/plan-check.js.map +1 -1
  164. package/dist/delivery/run-state.d.ts +1 -1
  165. package/dist/delivery/run-state.d.ts.map +1 -1
  166. package/dist/delivery/run-state.js +8 -1
  167. package/dist/delivery/run-state.js.map +1 -1
  168. package/dist/delivery/task-orchestrator.d.ts +8 -3
  169. package/dist/delivery/task-orchestrator.d.ts.map +1 -1
  170. package/dist/delivery/task-orchestrator.js +75 -43
  171. package/dist/delivery/task-orchestrator.js.map +1 -1
  172. package/dist/delivery/task-sync.d.ts +21 -0
  173. package/dist/delivery/task-sync.d.ts.map +1 -1
  174. package/dist/delivery/task-sync.js +44 -8
  175. package/dist/delivery/task-sync.js.map +1 -1
  176. package/dist/delivery/task-workspace.d.ts +3 -3
  177. package/dist/delivery/task-workspace.js +3 -3
  178. package/dist/generators/self-card.d.ts +65 -0
  179. package/dist/generators/self-card.d.ts.map +1 -0
  180. package/dist/generators/self-card.js +256 -0
  181. package/dist/generators/self-card.js.map +1 -0
  182. package/dist/inference/probe.js +1 -1
  183. package/dist/inference/probe.js.map +1 -1
  184. package/dist/memory/prepopulate.d.ts.map +1 -1
  185. package/dist/memory/prepopulate.js +2 -0
  186. package/dist/memory/prepopulate.js.map +1 -1
  187. package/dist/models/analytics.d.ts +32 -0
  188. package/dist/models/analytics.d.ts.map +1 -1
  189. package/dist/models/analytics.js +68 -5
  190. package/dist/models/analytics.js.map +1 -1
  191. package/dist/models/plan-readability.d.ts +55 -0
  192. package/dist/models/plan-readability.d.ts.map +1 -0
  193. package/dist/models/plan-readability.js +339 -0
  194. package/dist/models/plan-readability.js.map +1 -0
  195. package/dist/placement/admission.d.ts +59 -0
  196. package/dist/placement/admission.d.ts.map +1 -0
  197. package/dist/placement/admission.js +197 -0
  198. package/dist/placement/admission.js.map +1 -0
  199. package/dist/placement/auto.d.ts +44 -0
  200. package/dist/placement/auto.d.ts.map +1 -0
  201. package/dist/placement/auto.js +212 -0
  202. package/dist/placement/auto.js.map +1 -0
  203. package/dist/placement/enforce.d.ts +128 -0
  204. package/dist/placement/enforce.d.ts.map +1 -0
  205. package/dist/placement/enforce.js +655 -0
  206. package/dist/placement/enforce.js.map +1 -0
  207. package/dist/placement/idle.d.ts +50 -0
  208. package/dist/placement/idle.d.ts.map +1 -0
  209. package/dist/placement/idle.js +213 -0
  210. package/dist/placement/idle.js.map +1 -0
  211. package/dist/placement/ledger.d.ts +323 -0
  212. package/dist/placement/ledger.d.ts.map +1 -0
  213. package/dist/placement/ledger.js +263 -0
  214. package/dist/placement/ledger.js.map +1 -0
  215. package/dist/placement/preview.d.ts +51 -0
  216. package/dist/placement/preview.d.ts.map +1 -0
  217. package/dist/placement/preview.js +61 -0
  218. package/dist/placement/preview.js.map +1 -0
  219. package/dist/placement/probes.d.ts +47 -0
  220. package/dist/placement/probes.d.ts.map +1 -0
  221. package/dist/placement/probes.js +207 -0
  222. package/dist/placement/probes.js.map +1 -0
  223. package/dist/placement/proxy-env.d.ts +21 -0
  224. package/dist/placement/proxy-env.d.ts.map +1 -0
  225. package/dist/placement/proxy-env.js +42 -0
  226. package/dist/placement/proxy-env.js.map +1 -0
  227. package/dist/placement/registry.d.ts +1038 -0
  228. package/dist/placement/registry.d.ts.map +1 -0
  229. package/dist/placement/registry.js +274 -0
  230. package/dist/placement/registry.js.map +1 -0
  231. package/dist/policies/liveness.d.ts +6 -8
  232. package/dist/policies/liveness.d.ts.map +1 -1
  233. package/dist/policies/liveness.js +6 -25
  234. package/dist/policies/liveness.js.map +1 -1
  235. package/dist/policies/sandbox-anchor.d.ts +91 -0
  236. package/dist/policies/sandbox-anchor.d.ts.map +1 -0
  237. package/dist/policies/sandbox-anchor.js +187 -0
  238. package/dist/policies/sandbox-anchor.js.map +1 -0
  239. package/dist/policies/sandbox-grants.d.ts +131 -0
  240. package/dist/policies/sandbox-grants.d.ts.map +1 -0
  241. package/dist/policies/sandbox-grants.js +562 -0
  242. package/dist/policies/sandbox-grants.js.map +1 -0
  243. package/dist/state/manifest.d.ts +4 -2
  244. package/dist/state/manifest.d.ts.map +1 -1
  245. package/dist/state/manifest.js +32 -16
  246. package/dist/state/manifest.js.map +1 -1
  247. package/dist/utils/checkout-root.d.ts +2 -0
  248. package/dist/utils/checkout-root.d.ts.map +1 -0
  249. package/dist/utils/checkout-root.js +43 -0
  250. package/dist/utils/checkout-root.js.map +1 -0
  251. package/dist/utils/resolve-uap-bin.d.ts +5 -0
  252. package/dist/utils/resolve-uap-bin.d.ts.map +1 -0
  253. package/dist/utils/resolve-uap-bin.js +33 -0
  254. package/dist/utils/resolve-uap-bin.js.map +1 -0
  255. package/dist/utils/terminal-safe.d.ts +12 -0
  256. package/dist/utils/terminal-safe.d.ts.map +1 -0
  257. package/dist/utils/terminal-safe.js +53 -0
  258. package/dist/utils/terminal-safe.js.map +1 -0
  259. package/docs/ATTRIBUTION.md +1 -0
  260. package/docs/DASHBOARD_UPLIFT_SPEC.md +8 -8
  261. package/docs/INDEX.md +6 -5
  262. package/docs/architecture/OVERVIEW.md +15 -3
  263. package/docs/architecture/PROTOCOL.md +7 -1
  264. package/docs/architecture/adr/0006-operator-directed-model-placement.md +86 -0
  265. package/docs/architecture/adr/0007-auto-displacement-allowlist-as-standing-consent.md +79 -0
  266. package/docs/architecture/adr/0008-fleet-clients-link-out.md +92 -0
  267. package/docs/architecture/adr/0009-completion-triggered-dispatch-and-per-leaf-model-dials.md +71 -0
  268. package/docs/architecture/adr/0010-attention-queue-and-afk-auto-decider.md +159 -0
  269. package/docs/architecture/adr/0011-sandbox-grants-and-network-egress-boundary.md +219 -0
  270. package/docs/architecture/adr/0012-operator-legibility-surfaces.md +175 -0
  271. package/docs/getting-started/INSTALLATION.md +1 -1
  272. package/docs/guides/AUTOMATIC_FEATURES.md +8 -0
  273. package/docs/guides/LOCAL_MODELS.md +1 -1
  274. package/docs/guides/PROXY.md +2 -1
  275. package/docs/guides/SANDBOX.md +91 -4
  276. package/docs/integrations/MCP_ROUTER.md +1 -1
  277. package/docs/plans/model-performance-proof-options.md +176 -0
  278. package/docs/reference/API.md +1 -1
  279. package/docs/reference/CLI.md +169 -4
  280. package/docs/reference/COMPARISON.md +1 -1
  281. package/docs/reference/CONFIGURATION.md +12 -3
  282. package/docs/reference/CONFIGURATION_REFERENCE.md +269 -14
  283. package/docs/reference/DATABASE_SCHEMA.md +1 -1
  284. package/docs/reference/FEATURES.md +15 -3
  285. package/docs/reference/PATTERNS.md +1 -1
  286. package/docs/reference/PLATFORMS.md +14 -1
  287. package/docs/specs/operator-model-placement.md +1314 -0
  288. package/docs/specs/operator-model-placement.review.md +339 -0
  289. package/package.json +2 -2
  290. package/scripts/maintenance/publish-npm.sh +23 -11
  291. package/scripts/version-bump.sh +6 -51
  292. package/src/policies/enforcers/__pycache__/_common.cpython-311.pyc +0 -0
  293. package/src/policies/enforcers/__pycache__/expert_review_required.cpython-311.pyc +0 -0
  294. package/src/policies/enforcers/__pycache__/quality_metrics_gate.cpython-311.pyc +0 -0
  295. package/src/policies/schemas/policies/mandatory-testing-deployment.md +2 -5
  296. package/templates/hooks/__pycache__/deliver_autoroute.cpython-311.pyc +0 -0
  297. package/templates/hooks/session-start.sh +44 -0
  298. package/tools/agents/UAP/cli.py +14 -3
  299. package/tools/agents/UAP/paths.py +50 -0
  300. package/tools/agents/scripts/__pycache__/toolcall_path_normalizer.cpython-311.pyc +0 -0
  301. package/tools/agents/scripts/anthropic_proxy.py +1386 -99
  302. package/tools/agents/scripts/toolcall_path_normalizer.py +46 -1
  303. package/tools/agents/tests/test_anthropic_proxy_streaming.py +29 -6
  304. package/tools/agents/tests/test_doubling_break.py +64 -5
  305. package/tools/agents/tests/test_error_loop_break.py +10 -4
  306. package/tools/agents/tests/test_error_loop_ignores_correctives.py +13 -2
  307. package/tools/agents/tests/test_lockstep_escalation.py +280 -9
  308. package/tools/agents/tests/test_path_containment.py +94 -0
  309. package/tools/agents/tests/test_proxy_unix_socket.py +162 -0
  310. package/tools/agents/tests/test_signature_quality.py +349 -0
  311. package/tools/agents/tests/test_uap_compliance.py +11 -1
  312. package/web/dash/core.js +1 -0
  313. package/web/dash/tab-clients.js +196 -0
  314. package/web/dash/tab-models.js +387 -8
  315. package/web/dash/tab-policies.js +87 -4
  316. package/web/dash/tabs.js +77 -73
  317. package/web/dashboard.html +6 -0
  318. package/src/policies/enforcers/__pycache__/_common.cpython-312.pyc +0 -0
  319. package/src/policies/enforcers/__pycache__/expert_review_required.cpython-312.pyc +0 -0
  320. package/src/policies/enforcers/__pycache__/quality_metrics_gate.cpython-312.pyc +0 -0
  321. package/templates/hooks/__pycache__/deliver_autoroute.cpython-312.pyc +0 -0
  322. package/tools/agents/scripts/__pycache__/toolcall_path_normalizer.cpython-312.pyc +0 -0
  323. package/web/dash/tab-agents.js +0 -21
  324. package/web/dash/tab-deliver.js +0 -12
  325. package/web/dash/tab-memory.js +0 -12
  326. package/web/dash/tab-orchestration.js +0 -21
  327. package/web/dash/tab-overview.js +0 -21
  328. package/web/dash/tab-tasks.js +0 -21
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Implementation-State Manifest — a machine-generated snapshot of what this
3
3
  * project IS and where its implementation actually stands, derived from
4
- * ground truth (package.json, CHANGELOG, git branch, .factory registries)
4
+ * ground truth (package.json, git log, git branch, .factory registries)
5
5
  * rather than hand-maintained docs that drift.
6
6
  *
7
7
  * Written to `.uap/state-manifest.json`; the reactor injects a one-line
@@ -12,6 +12,7 @@
12
12
  import { execFileSync } from 'child_process';
13
13
  import { existsSync, mkdirSync, readFileSync, readdirSync, renameSync, statSync, writeFileSync } from 'fs';
14
14
  import { join } from 'path';
15
+ import { termSafeBounded } from '../utils/terminal-safe.js';
15
16
  const RECENT_CHANGES = 5;
16
17
  /** Digest re-generation threshold: a manifest older than this is stale. */
17
18
  const STALE_MS = 24 * 60 * 60 * 1000;
@@ -35,6 +36,30 @@ function gitBranch(projectRoot) {
35
36
  return undefined;
36
37
  }
37
38
  }
39
+ /** Latest commit subjects, newest first — straight from the git log. Commit
40
+ * subjects are contributor-authored (untrusted) text: termSafeBounded strips
41
+ * terminal-control bytes, flattens to one line, and bounds the length, so a
42
+ * hostile subject cannot smuggle escapes or line structure into the digest. */
43
+ function gitSubjects(projectRoot) {
44
+ try {
45
+ const out = execFileSync('git', ['log', '--pretty=%s', '-n', String(RECENT_CHANGES), '--no-merges'], {
46
+ cwd: projectRoot,
47
+ encoding: 'utf-8',
48
+ timeout: 3000,
49
+ stdio: ['ignore', 'pipe', 'ignore'],
50
+ // Never inherit a poisoned GIT_DIR from a hook environment.
51
+ env: { ...process.env, GIT_DIR: undefined, GIT_WORK_TREE: undefined, GIT_INDEX_FILE: undefined },
52
+ });
53
+ return out
54
+ .split('\n')
55
+ .map((line) => termSafeBounded(line, 160))
56
+ .filter(Boolean);
57
+ }
58
+ catch {
59
+ // not a git repo (or git unusable) — manifest still useful without it
60
+ return [];
61
+ }
62
+ }
38
63
  function countEntries(dir) {
39
64
  try {
40
65
  if (!existsSync(dir))
@@ -59,20 +84,7 @@ export function generateStateManifest(projectRoot) {
59
84
  }
60
85
  const name = typeof pkg.name === 'string' ? pkg.name : 'unknown';
61
86
  const version = typeof pkg.version === 'string' ? pkg.version : '0.0.0';
62
- const recentChanges = [];
63
- try {
64
- const changelog = readFileSync(join(projectRoot, 'CHANGELOG.md'), 'utf-8');
65
- for (const line of changelog.split('\n')) {
66
- if (line.startsWith('## ')) {
67
- recentChanges.push(line.slice(3).trim().slice(0, 160));
68
- if (recentChanges.length >= RECENT_CHANGES)
69
- break;
70
- }
71
- }
72
- }
73
- catch {
74
- // no changelog — manifest still useful
75
- }
87
+ const recentChanges = gitSubjects(projectRoot);
76
88
  const counts = {};
77
89
  const skillCount = countEntries(join(projectRoot, '.factory', 'skills'));
78
90
  const droidCount = countEntries(join(projectRoot, '.factory', 'droids'));
@@ -140,7 +152,11 @@ export function manifestDigest(manifest) {
140
152
  `${manifest.name} v${manifest.version}${manifest.branch ? ` (branch: ${manifest.branch})` : ''}`,
141
153
  ];
142
154
  if (manifest.recentChanges.length > 0) {
143
- lines.push(`Recently shipped: ${manifest.recentChanges.slice(0, 3).join(' | ')}`.slice(0, 240));
155
+ // Choke-point defense: on the load path (readOrRefreshManifest) these
156
+ // entries can come from a planted .uap/state-manifest.json — re-strip
157
+ // before the digest reaches a session prompt.
158
+ const subjects = manifest.recentChanges.map((s) => termSafeBounded(s, 160));
159
+ lines.push(`Recently shipped: ${subjects.slice(0, 3).join(' | ')}`.slice(0, 240));
144
160
  }
145
161
  if (manifest.counts) {
146
162
  lines.push(Object.entries(manifest.counts)
@@ -1 +1 @@
1
- {"version":3,"file":"manifest.js","sourceRoot":"","sources":["../../src/state/manifest.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"manifest.js","sourceRoot":"","sources":["../../src/state/manifest.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function mainCheckoutRoot(projectRoot: string): string;
2
+ //# sourceMappingURL=checkout-root.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"checkout-root.d.ts","sourceRoot":"","sources":["../../src/utils/checkout-root.ts"],"names":[],"mappings":"AAoBA,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAqB5D"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * The main-checkout root anchor (moved from src/policies/liveness.ts so
3
+ * non-policy state can share it without importing the policies layer).
4
+ *
5
+ * The gate hook strips `/.worktrees/<name>` to find it
6
+ * (${CHECKOUT_ROOT%%/.worktrees/*}); the writers must anchor the same way or
7
+ * a worktree session — the workflow CLAUDE.md MANDATES — writes state and
8
+ * reads it back where other surfaces never look (review should-fix,
9
+ * 2026-07-13; reintroduced as a BLOCKER by the 2026-10-11 attention-queue
10
+ * review: dashboard cwd, hook PROJECT_DIR, and CLI cwd resolved three
11
+ * different queue files). Non-git roots (unit fixtures, tmp dirs) pass
12
+ * through unchanged.
13
+ */
14
+ import { spawnSync } from 'child_process';
15
+ import { sep } from 'path';
16
+ /** Roots are stable for a process lifetime; callers resolve this on every
17
+ * queue read/write and must not spawn git per call. */
18
+ const cache = new Map();
19
+ export function mainCheckoutRoot(projectRoot) {
20
+ const hit = cache.get(projectRoot);
21
+ if (hit !== undefined)
22
+ return hit;
23
+ let root = projectRoot;
24
+ try {
25
+ const r = spawnSync('git', ['rev-parse', '--show-toplevel'], {
26
+ cwd: projectRoot,
27
+ encoding: 'utf-8',
28
+ });
29
+ if (r.status === 0) {
30
+ const top = (r.stdout ?? '').trim();
31
+ if (top) {
32
+ const i = top.indexOf(`${sep}.worktrees${sep}`);
33
+ root = i === -1 ? top : top.slice(0, i);
34
+ }
35
+ }
36
+ }
37
+ catch {
38
+ root = projectRoot;
39
+ }
40
+ cache.set(projectRoot, root);
41
+ return root;
42
+ }
43
+ //# sourceMappingURL=checkout-root.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"checkout-root.js","sourceRoot":"","sources":["../../src/utils/checkout-root.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC1C,OAAO,EAAE,GAAG,EAAE,MAAM,MAAM,CAAC;AAE3B;wDACwD;AACxD,MAAM,KAAK,GAAG,IAAI,GAAG,EAAkB,CAAC;AAExC,MAAM,UAAU,gBAAgB,CAAC,WAAmB;IAClD,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;IACnC,IAAI,GAAG,KAAK,SAAS;QAAE,OAAO,GAAG,CAAC;IAClC,IAAI,IAAI,GAAG,WAAW,CAAC;IACvB,IAAI,CAAC;QACH,MAAM,CAAC,GAAG,SAAS,CAAC,KAAK,EAAE,CAAC,WAAW,EAAE,iBAAiB,CAAC,EAAE;YAC3D,GAAG,EAAE,WAAW;YAChB,QAAQ,EAAE,OAAO;SAClB,CAAC,CAAC;QACH,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACnB,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;YACpC,IAAI,GAAG,EAAE,CAAC;gBACR,MAAM,CAAC,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,GAAG,aAAa,GAAG,EAAE,CAAC,CAAC;gBAChD,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;YAC1C,CAAC;QACH,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,IAAI,GAAG,WAAW,CAAC;IACrB,CAAC;IACD,KAAK,CAAC,GAAG,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;IAC7B,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -0,0 +1,5 @@
1
+ export declare function resolveUapBin(): {
2
+ cmd: string;
3
+ preArgs: string[];
4
+ };
5
+ //# sourceMappingURL=resolve-uap-bin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve-uap-bin.d.ts","sourceRoot":"","sources":["../../src/utils/resolve-uap-bin.ts"],"names":[],"mappings":"AAeA,wBAAgB,aAAa,IAAI;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAA;CAAE,CAclE"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Resolve the uap executable for detached child spawns (deliver launch/resume,
3
+ * fleet dashboard spawn-on-demand).
4
+ *
5
+ * PATH often lacks the npm global bin, and a launch that silently died with
6
+ * ENOENT was a real dash-audit hazard. Resolution order:
7
+ * 1. UAP_BIN env override (operator/debug).
8
+ * 2. This module's own install: <root>/dist/bin/cli.js run with the SAME
9
+ * node binary that runs the dashboard (no PATH, no shell).
10
+ * 3. Bare 'uap' as the last resort (interactive PATH).
11
+ */
12
+ import { existsSync } from 'fs';
13
+ import { join, dirname } from 'path';
14
+ import { fileURLToPath } from 'url';
15
+ export function resolveUapBin() {
16
+ if (process.env.UAP_BIN)
17
+ return { cmd: process.env.UAP_BIN, preArgs: [] };
18
+ try {
19
+ // ESM: this file is <root>/dist/utils/resolve-uap-bin.js
20
+ const selfUrl = import.meta.url;
21
+ if (selfUrl.startsWith('file:')) {
22
+ const here = fileURLToPath(selfUrl);
23
+ const cli = join(dirname(here), '..', 'bin', 'cli.js');
24
+ if (existsSync(cli))
25
+ return { cmd: process.execPath, preArgs: [cli] };
26
+ }
27
+ }
28
+ catch {
29
+ /* fall through to PATH */
30
+ }
31
+ return { cmd: 'uap', preArgs: [] };
32
+ }
33
+ //# sourceMappingURL=resolve-uap-bin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve-uap-bin.js","sourceRoot":"","sources":["../../src/utils/resolve-uap-bin.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AAChC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AACrC,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AAEpC,MAAM,UAAU,aAAa;IAC3B,IAAI,OAAO,CAAC,GAAG,CAAC,OAAO;QAAE,OAAO,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;IAC1E,IAAI,CAAC;QACH,yDAAyD;QACzD,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC;QAChC,IAAI,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;YAChC,MAAM,IAAI,GAAG,aAAa,CAAC,OAAO,CAAC,CAAC;YACpC,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC;YACvD,IAAI,UAAU,CAAC,GAAG,CAAC;gBAAE,OAAO,EAAE,GAAG,EAAE,OAAO,CAAC,QAAQ,EAAE,OAAO,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC;QACxE,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,0BAA0B;IAC5B,CAAC;IACD,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;AACrC,CAAC"}
@@ -0,0 +1,12 @@
1
+ /** Strip terminal-control bytes (keeps tab/newline/CR). */
2
+ export declare function termSafe(s: string): string;
3
+ /**
4
+ * Same strip, then flatten to ONE line and bound the length — for strings
5
+ * that become prompt text or single-line display fields (model ids, labels).
6
+ * Line breaks are structure a hostile string must not smuggle in: collapsing
7
+ * them to a space keeps the text honest and the shape fixed.
8
+ */
9
+ export declare function termSafeBounded(s: string, max: number): string;
10
+ /** Strip ANSI escape sequences and every C0/C1 control byte (incl. newline). */
11
+ export declare function stripControlChars(text: string): string;
12
+ //# sourceMappingURL=terminal-safe.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"terminal-safe.d.ts","sourceRoot":"","sources":["../../src/utils/terminal-safe.ts"],"names":[],"mappings":"AAcA,2DAA2D;AAC3D,wBAAgB,QAAQ,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAE1C;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAK9D;AAmBD,gFAAgF;AAChF,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAKtD"}
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Terminal-safe rendering — strip the C0/C1 control
3
+ * characters that could steer an operator's terminal from data we did not
4
+ * author: JSON report fields, analytics-store model ids, commit subjects.
5
+ *
6
+ * Kept characters: `\t`, `\n`, `\r` (layout, not control); everything else in
7
+ * C0 (U+0000–U+001F), DEL (U+007F), and C1 (U+0080–U+009F) is removed. This
8
+ * is defense-in-depth at ONE choke point, not a trust boundary: the strings
9
+ * it cleans come from repo/store files an operator could equally `cat` — but
10
+ * a UAP surface must not be a better terminal-injection mule than `cat`.
11
+ */
12
+ // eslint-disable-next-line no-control-regex -- matching control bytes IS this module's job; the regex strips what it matches
13
+ const CONTROL_CHARS = /[\u0000-\u0008\u000B\u000C\u000E-\u001F\u007F-\u009F]/g;
14
+ /** Strip terminal-control bytes (keeps tab/newline/CR). */
15
+ export function termSafe(s) {
16
+ return s.replace(CONTROL_CHARS, '');
17
+ }
18
+ /**
19
+ * Same strip, then flatten to ONE line and bound the length — for strings
20
+ * that become prompt text or single-line display fields (model ids, labels).
21
+ * Line breaks are structure a hostile string must not smuggle in: collapsing
22
+ * them to a space keeps the text honest and the shape fixed.
23
+ */
24
+ export function termSafeBounded(s, max) {
25
+ return termSafe(s)
26
+ .replace(/\s+/g, ' ')
27
+ .trim()
28
+ .slice(0, max);
29
+ }
30
+ /**
31
+ * Sequence-aware strip — the strong form of `termSafe`. Removes whole ANSI
32
+ * OSC sequences (hyperlinks, window-title writes) and CSI sequences (colors,
33
+ * cursor movement) BEFORE deleting the remaining C0/C1 bytes. `termSafe` only
34
+ * deletes bytes, leaving a sequence's payload characters behind (an OSC-52
35
+ * clipboard write defangs to `]52;c;base64…`); this form removes the sequence
36
+ * entire. Unlike `termSafe` it also removes `\t`/`\n`/`\r` — callers that
37
+ * need single-line output or preserved layout must normalize whitespace
38
+ * FIRST, because a newline deleted after normalization cannot glue two
39
+ * words together.
40
+ */
41
+ /* eslint-disable no-control-regex -- matching control bytes IS this module's job; the regexes strip what they match */
42
+ const OSC_SEQUENCE = /\x1b\][^\x07\x1b]*(?:\x07|\x1b\\)/g;
43
+ const CSI_SEQUENCE = /\x1b\[[0-9;?]*[ -/]*[@-~]/g;
44
+ const ANY_CONTROL_BYTE = /[\x00-\x1f\x7f-\x9f]/g;
45
+ /* eslint-enable no-control-regex */
46
+ /** Strip ANSI escape sequences and every C0/C1 control byte (incl. newline). */
47
+ export function stripControlChars(text) {
48
+ return text
49
+ .replace(OSC_SEQUENCE, '')
50
+ .replace(CSI_SEQUENCE, '')
51
+ .replace(ANY_CONTROL_BYTE, '');
52
+ }
53
+ //# sourceMappingURL=terminal-safe.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"terminal-safe.js","sourceRoot":"","sources":["../../src/utils/terminal-safe.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,6HAA6H;AAC7H,MAAM,aAAa,GAAG,wDAAwD,CAAC;AAE/E,2DAA2D;AAC3D,MAAM,UAAU,QAAQ,CAAC,CAAS;IAChC,OAAO,CAAC,CAAC,OAAO,CAAC,aAAa,EAAE,EAAE,CAAC,CAAC;AACtC,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,eAAe,CAAC,CAAS,EAAE,GAAW;IACpD,OAAO,QAAQ,CAAC,CAAC,CAAC;SACf,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC;SACpB,IAAI,EAAE;SACN,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;AACnB,CAAC;AAED;;;;;;;;;;GAUG;AACH,uHAAuH;AACvH,MAAM,YAAY,GAAG,oCAAoC,CAAC;AAC1D,MAAM,YAAY,GAAG,4BAA4B,CAAC;AAClD,MAAM,gBAAgB,GAAG,uBAAuB,CAAC;AACjD,oCAAoC;AAEpC,gFAAgF;AAChF,MAAM,UAAU,iBAAiB,CAAC,IAAY;IAC5C,OAAO,IAAI;SACR,OAAO,CAAC,YAAY,EAAE,EAAE,CAAC;SACzB,OAAO,CAAC,YAAY,EAAE,EAAE,CAAC;SACzB,OAAO,CAAC,gBAAgB,EAAE,EAAE,CAAC,CAAC;AACnC,CAAC"}
@@ -27,6 +27,7 @@ The full dependency graph lives in `package.json`; these deserve explicit mentio
27
27
  because UAP embeds, vendors, or builds core workflows around them:
28
28
 
29
29
  - **[llama.cpp](https://github.com/ggml-org/llama.cpp) / ik_llama.cpp** — the local inference backend the whole local-model path (deliver, recipes, slot budgeting) is built against.
30
+ - **[bubblewrap](https://github.com/containers/bubblewrap)** (GNOME) — the unprivileged kernel sandbox (`uap sandbox`) behind the sandboxed delivery path: read-only root mounts, per-session writable holes, and the `--unshare-net` egress cut are all bwrap primitives.
30
31
  - **Qwen** (Alibaba) — the local models UAP's local-first delivery pipeline is tuned for and benchmarked with.
31
32
  - **[Qdrant](https://qdrant.tech/)** + **nomic-embed-text** — the semantic long-term memory store and its embeddings.
32
33
  - **[uPlot](https://github.com/leeoniya/uPlot)** (MIT) — vendored (with license) in `web/vendor/` for the dashboard's charts.
@@ -26,14 +26,14 @@ web/dash/core.js data layer + app shell: WS/SSE/poll channels, global
26
26
  api() POST helper, expand/collapse helpers, drill navigation (goAgent(id)).
27
27
  web/dash/charts.js uPlot chart + sparkline builders (ported 1:1 from current behaviour).
28
28
  web/dash/styles.css all CSS (ported + new tab/drawer/table/control styles), tokens only.
29
- web/dash/tab-overview.js aggregate KPIs + hero charts + live summaries with drill links.
30
- web/dash/tab-tasks.js Tasks & Epics: kanban + table + create/edit/status/assignee/delete + epic ledger.
31
- web/dash/tab-agents.js Agents & Sessions: agent grid -> per-agent drawer; session history -> per-session drawer.
32
- web/dash/tab-orchestration.js mission->epic->task tree + agents + orchestrate on/off/auto + ledger controls.
33
- web/dash/tab-deliver.js deliver run registry list + launch form + cancel/resume + per-run telemetry.
34
- web/dash/tab-policies.js policies table (existing controls) + compliance + audit + live events.
35
- web/dash/tab-models.js models/routing config + session usage + routing decisions.
36
- web/dash/tab-memory.js L1-L4 + compression + hit/miss gauge + recent queries + savings-by-influence.
29
+ web/dash/tabs.js inline tabs: overview (+ service-health strip) / tasks & epics kanban /
30
+ agents / orchestration / deliver / memory. (The six per-tab stub
31
+ files were dead weight — never loaded by dashboard.html — and
32
+ were removed.)
33
+ web/dash/tab-policies.js full policies panel (order/view/duplicate/import/export) +
34
+ compliance + audit + live events.
35
+ web/dash/tab-models.js models & placement: registry, ledger, pending placement
36
+ apply/dismiss, unload, auto-load policy, preview.
37
37
  ```
38
38
  Server change: `server.ts` static handler currently serves `/vendor/`; extend it to ALSO serve
39
39
  `/dash/` (same path-traversal guard, content types add `.css`, `.js`).
package/docs/INDEX.md CHANGED
@@ -1,13 +1,13 @@
1
1
  # UAP Documentation
2
2
 
3
- The complete documentation for the **Universal Agent Protocol** (`@miller-tech/uap` v2.11.0) — the discipline layer that turns a talented-but-unreliable AI coding agent into a dependable member of your software delivery line. 367 TypeScript modules across 26 subsystems, 459 vitest suites plus a ~1,200-test Python enforcer/proxy suite, 60+ CLI command registrations, 32 executable policy enforcers, 9 supported agent harnesses.
3
+ The complete documentation for the **Universal Agent Protocol** (`@miller-tech/uap`) — the discipline layer that turns a talented-but-unreliable AI coding agent into a dependable member of your software delivery line. 447 TypeScript modules across 34 subsystems, 530 vitest suites (~6,250 tests) plus a ~1,400-test Python enforcer/proxy suite, 60 top-level CLI commands (~211 registrations including subcommands), 34 executable policy enforcers, 9 supported agent harnesses.
4
4
 
5
5
  > **Reviewing the system?** The reverse-engineered, code-verified reference set lives in
6
6
  > [`documentation/`](../documentation/architecture.md): architecture, flows, permissions
7
7
  > (incl. trust boundaries and enforcement gaps), variables/secrets, scheduled work, and
8
8
  > embedded automation. Start there for an honest map of what's enforced vs. documented.
9
9
 
10
- New here? The friendliest way in is the **[Delivery Pipeline tour](guides/DELIVERY_PIPELINE.md)** — it walks the whole factory floor, station by station, showing where agents normally break and what UAP puts in place to catch it. Then grab the [Quickstart](getting-started/QUICKSTART.md).
10
+ New here? Start with the **[Delivery Pipeline tour](guides/DELIVERY_PIPELINE.md)** — it walks the whole factory floor, station by station, showing where agents normally break and what UAP puts in place to catch it, all under one principle: *enforce, don't suggest*. Then grab the [Quickstart](getting-started/QUICKSTART.md).
11
11
 
12
12
  ---
13
13
 
@@ -79,7 +79,7 @@ Full map: **[The UAP Delivery Pipeline](guides/DELIVERY_PIPELINE.md)**.
79
79
  | [Self-Harness](design/SELF_HARNESS.md) | Self-improving harness (shipped as `uap self-harness`): autonomous mine→propose→validate loop over a bounded Mod DSL; cross-model transfer, online mining |
80
80
  | [LLM Self-Tuning (analysis)](design/LLM_SELF_TUNING_ANALYSIS.md) | The design behind `uap tune`: quality signal, LLM-guided + Gaussian-process flag search, closed-loop validation, model profiles, real-time adaptation |
81
81
  | [Product Naming (analysis)](design/PRODUCT_NAMING.md) | UAP rename candidates: availability sweeps (npm/PyPI/domains), AI-space collision checks, railway-theme shortlist, recommendation. No decision committed; availability data is point-in-time |
82
- | [ADRs](architecture/adr/) | Architecture decision records: [0001 AutoMode risk floor](architecture/adr/0001-automode-risk-floor.md) (Python heuristic scorer ahead of the TS SYS1 head), [0002 Evidence-bound ship](architecture/adr/0002-evidence-bound-ship.md) (gate evidence bound to the candidate SHA) |
82
+ | [ADRs](architecture/adr/) | Architecture decision records: [0001 AutoMode risk floor](architecture/adr/0001-automode-risk-floor.md) (Python heuristic scorer ahead of the TS SYS1 head), [0002 Evidence-bound ship](architecture/adr/0002-evidence-bound-ship.md) (gate evidence bound to the candidate SHA), … [0009 Completion-triggered dispatch + per-leaf model dials](architecture/adr/0009-completion-triggered-dispatch-and-per-leaf-model-dials.md), [0010 Attention queue + AFK auto-decider](architecture/adr/0010-attention-queue-and-afk-auto-decider.md), [0011 Sandbox grants + network egress boundary](architecture/adr/0011-sandbox-grants-and-network-egress-boundary.md), [0012 Operator legibility surfaces](architecture/adr/0012-operator-legibility-surfaces.md) |
83
83
 
84
84
  ## Reference
85
85
 
@@ -137,11 +137,12 @@ the decision record.
137
137
 
138
138
  | Doc | What it covers |
139
139
  |---|---|
140
- | [Deliver hardening plan](plans/deliver-hardening-plan-2026-07-13.md) | The 14-defect audit (batches A–D) that became v1.224.0: scoped rollback, declared gates, polyglot execution, config routing, liveness, operator overrides |
140
+ | [Deliver hardening plan](plans/deliver-hardening-plan-2026-07-13.md) | The 14-defect hardening plan (batches A–D): scoped rollback, declared gates, polyglot execution, config routing, liveness, operator overrides |
141
141
  | [Deliver hardening review response](plans/deliver-hardening-review-response-2026-07-13.md) | Parallel-review findings and their dispositions — the rationale behind the root-owned trust model |
142
142
  | [Harness engineering uplift](plans/harness-engineering-uplift-2026-07-31.md) | Three-paper analysis of harness variance and what UAP does about it |
143
143
  | [K3 UAP uplift validation](plans/k3-uap-uplift-validation.md) | Plan to measure UAP's paired uplift on Kimi K3 by re-running Terminal-Bench 2.1 with Factory Droid as the harness, UAP on vs off |
144
- | [Qwen3.8 UAP re-test plan](plans/qwen38-uap-retest-plan.md) | Plan to re-run the paired benchmark matrix on the current local Qwen3.8-27B stack with UAP v1.224.x, replicating the +20pp gate-loop finding and checking the hardened deliver pipeline |
144
+ | [Qwen3.8 UAP re-test plan](plans/qwen38-uap-retest-plan.md) | Plan to re-run the paired benchmark matrix on the current local Qwen3.8-27B stack, replicating the +20pp gate-loop finding and checking the hardened deliver pipeline |
145
+ | [Model-performance proof options](plans/model-performance-proof-options.md) | The benchmark/test menu for demonstrating UAP's benefits with honest numbers: four separately-provable claims, six options (free-first), discrimination status required on every delta |
145
146
  | [System-1 uplift plan](plans/system1-uplift-2026-09-18.md) | Approved uplift from the 2026-09-18 ten-source analysis (Jev/Foreman/Fluent/CEK et al): Wave 0 quick wins + Wave 1 System-1 decision layer, local-only classifier trained from UAP telemetry |
146
147
 
147
148
  ## Specs & performance
@@ -1,6 +1,10 @@
1
1
  # UAP Architecture Overview
2
2
 
3
- `v1.224.0` · 367 TypeScript modules across 26 `src/` subsystems · 459 vitest suites (+ a ~1,200-test Python enforcer/proxy suite)
3
+ 447 TypeScript modules across 34 `src/` subsystems · 530 vitest suites (~6,250 tests, + a ~1,400-test Python enforcer/proxy suite)
4
+
5
+ > **Why it looks like this:** every station exists because a specific failure
6
+ > class shows up there in real agentic delivery — the architecture is the
7
+ > codified countermeasure, station by station.
4
8
 
5
9
  > **Code-verified reference:** this narrative overview is the intent-level floor plan. For
6
10
  > the reverse-engineered, implementation-accurate map — including trust boundaries,
@@ -52,6 +56,14 @@ to the subsystem that guards it. Read this as the conveyor belt your work rides:
52
56
  | **7. Shipping** — merge & release | regressions, broken CI, skipped version bumps | worktree→PR flow, version/completion gates, CI feedback watcher, never-regress, git-safety |
53
57
  | **8. Feedback** — learn from it | same mistake every session | **memory promotion**, pattern RL, session analysis |
54
58
 
59
+ Three stations are tightened against the failure classes named in
60
+ mtlynch.io's *Why Are Coding Agents So Dumb?*: plan **legibility** (a
61
+ readability gate over plans + the version-pinned **self-knowledge card**),
62
+ **scheduling** (completion-triggered dispatch with per-leaf model dials), and
63
+ **autonomy** (the attention queue + AFK auto-decider: the agent asks instead
64
+ of stopping, and an unattended decision adopts the recorded safe default,
65
+ logged, never silent).
66
+
55
67
  Cross-cutting through every station: **policy gates** are the executable rules
56
68
  posted at each station, the **MCP Router** keeps the context lean so the belt
57
69
  never jams, and UAP runs across **9 harnesses** so the same floor plan applies
@@ -255,7 +267,7 @@ interpreter-mediated writes), memory-before-plan, MCP-router-first,
255
267
  and more. Levels: **REQUIRED** blocks, **RECOMMENDED** logs,
256
268
  **OPTIONAL** informs.
257
269
 
258
- Two trust anchors sit above the policies themselves (v1.224): the
270
+ Two trust anchors sit above the policies themselves: the
259
271
  **operator-overrides file** (`.uap/operator-overrides.json` — temporary,
260
272
  expiring bypasses) and the **liveness cache** (`.uap/policy-liveness.json` —
261
273
  for policies that declare liveness requirements, a record that their compliant
@@ -273,7 +285,7 @@ compound invisibly until the codebase fights every change. This station turns
273
285
  ten software-quality metrics into a machine-checked budget that can only
274
286
  tighten.
275
287
 
276
- The quality-metrics gate (v1.223) polices cyclomatic/cognitive complexity,
288
+ The quality-metrics gate polices cyclomatic/cognitive complexity,
277
289
  Halstead difficulty, LOC-per-file, coverage, CRAP, surviving mutants, dead
278
290
  code, duplicate blocks, and explicit `any`/`unknown` — deterministically, with
279
291
  no LLM in the loop. The built-in scanner (LOC, complexity, any-types) always
@@ -1,6 +1,6 @@
1
1
  # The UAP Protocol
2
2
 
3
- `v1.224.0`
3
+ `v2.30.0`
4
4
 
5
5
  > **🏭 Where this fits:** Cross-cutting (the factory rulebook) — with no shared
6
6
  > contract, each station's rules are guesswork and your agent slips broken work
@@ -77,6 +77,12 @@ hook, which MUST:
77
77
  this in the agent's context.
78
78
  2. **Clean stale state.** Deregister dead agents and release abandoned work
79
79
  claims so coordination state stays accurate.
80
+ 3. **Surface waiting decisions.** Sweep the operator attention queue —
81
+ grace-elapsed asks adopt their recorded safe default (logged on the item,
82
+ never silent); asks with no safe default escalate — then emit a bounded
83
+ block of still-open asks (plus a while-you-were-away summary) into the
84
+ session banner. Item text is rendered with an untrusted-data disclaimer;
85
+ `UAP_ATTENTION_OFF=1` silences the rail end-to-end.
80
86
 
81
87
  The hook is **self-healing and fail-open**: it auto-creates missing
82
88
  coordination/memory DBs and never exits non-zero. Its output is advisory
@@ -0,0 +1,86 @@
1
+ # ADR 0006: Operator-directed model placement (registry + ledger + proxy gate)
2
+
3
+ - Status: Accepted
4
+ - Date: 2026-10-08
5
+ - Spec: `docs/specs/operator-model-placement.md`
6
+
7
+ ## Context
8
+
9
+ One 24 GiB GPU, seven placeable model configs, one of them resident and filling
10
+ the card (measured 21,812 MiB of 24,576; host RSS 52.9 GiB of 121.7 GiB). Model
11
+ switching today is a hand-run shell script (`~/.config/uap/model-switch.sh`)
12
+ with no drain, no verification, and no rollback. The proxy forwards to a single
13
+ upstream (`LLAMA_CPP_BASE`, one constant, 35 references) and has no model
14
+ lifecycle at all. Requests for a non-resident model either fail or silently get
15
+ rewritten by `_reconcile_wire_model()`.
16
+
17
+ ## Decision
18
+
19
+ 1. **Two-file registry.** Reviewed defaults in `config/model-registry.json`,
20
+ machine-local measured footprints in `~/.uap/model-registry.json`,
21
+ deep-merged local-over-repo, with per-field provenance reported by
22
+ `uap models validate`. Unknown cost fails closed: an unmeasured config can
23
+ be served if resident but can never be loaded or evicted. The registry
24
+ references the capacity policy rather than restating its numbers (ownership
25
+ table in the spec, §4.1).
26
+ 2. **Placement state lives in a versioned, advisory-locked ledger**
27
+ (`~/.uap/placement.json`). The ledger records intent; a live probe records
28
+ fact; when they disagree the probe wins and the disagreement is surfaced.
29
+ 3. **Enforcement is TypeScript, hosted on the dashboard server, invoked by the
30
+ Python proxy over loopback HTTP.** No new daemon; one process owns placement
31
+ state, and the TUI and dashboard read the same one. The proxy discovers the
32
+ controller via `PROXY_PLACEMENT_CONTROLLER` emitted by `uap setup`; the
33
+ control surface is loopback-bound regardless of the dashboard `--host`.
34
+ 4. **`paused` means weights offloaded and reloaded from disk later** — not the
35
+ proxy's existing save/restore, which checkpoints KV to host RAM and frees no
36
+ VRAM. Where an engine has no reload path, `paused` is display-only and the
37
+ only executable option is `kill`.
38
+ 5. **Admission runs in the proxy after wire-model resolution**, default
39
+ `PROXY_PLACEMENT_MODE=off`, gated per entry route (the gate is a function of
40
+ the resolved wire model, not a side effect of one route's rewrite step —
41
+ `_reconcile_wire_model` has exactly one call site). Parked requests get
42
+ `409 model_placement_pending`; the proxy never holds a socket across an
43
+ unbounded operator decision. A swap invalidates the proxy's process-lifetime
44
+ upstream-id cache before any pending request is released.
45
+ 6. **Leases and backpressure become target-keyed** with an additive
46
+ `target = 'default'` legacy bucket, preserving the
47
+ delete-then-count-then-insert transaction ordering that makes
48
+ `acquireModelSlot()` safe today. `target` is the placement target identity
49
+ (device + endpoint), never the model name. The migration is guarded by a
50
+ `PRAGMA table_info` probe (the coordination DB has no version marker), on the
51
+ precedent of `src/memory/short-term/schema.ts`.
52
+
53
+ ## Consequences
54
+
55
+ Positive: placement decisions become data (`uap doctor`, `uap models validate`)
56
+ instead of prose in profile files; displacement is expressed in MiB rather than
57
+ unit names; the operator sees the victim list before committing, and
58
+ enforcement aborts if the re-derived list differs.
59
+
60
+ Negative: the proxy gains a control-plane dependency on the dashboard process
61
+ (no dashboard means read-only admission and `reason: no_controller`); the
62
+ teardown/start time envelope is unmeasured, so drain and hold timeouts ship as
63
+ conservative defaults labelled unvalidated; the coordination DB gains a table
64
+ rebuild with no version marker, so the migration must be probe-guarded;
65
+ per-target upstream addressing (phase 1.5) is a prerequisite refactor in the
66
+ 17k-line proxy and cannot be skipped.
67
+
68
+ Neutral: `uap models` sits next to the existing `uap model` command.
69
+
70
+ ## Alternatives Considered
71
+
72
+ - **Enforcement in the proxy (Python).** Rejected: the proxy has no subprocess
73
+ or systemd machinery in 17k lines, and the TS side already owns the units,
74
+ the capacity policy, the lease ledger, and the dashboard.
75
+ - **A dedicated placement daemon.** Rejected: two processes holding placement
76
+ state, and a new thing to supervise on a box that already supervises too
77
+ much.
78
+ - **Derive cost from GGUF file sizes.** Rejected by measurement: 79 GiB on disk
79
+ for a 21.8 GiB GPU footprint, and 15 GiB on disk for a config needing 22+ GiB.
80
+ Disk size is not a proxy for anything.
81
+ - **Use the existing save/restore path for `paused`.** Rejected: it frees no
82
+ VRAM, costs 10-20 s per slot, and may not fit in ~29 GiB of available host
83
+ RAM against a 52.9 GiB resident process.
84
+ - **Advertise a fixed VRAM cost per model.** Rejected: cost is per config and
85
+ drifts with engine build and flags; unmeasured entries are marked
86
+ `unmeasured` rather than guessed.
@@ -0,0 +1,79 @@
1
+ # ADR 0007: Auto-displacement allowlist as standing operator consent
2
+
3
+ - Status: Accepted
4
+ - Date: 2026-10-09
5
+ - Spec: `docs/specs/operator-model-placement.md` §4.4.1, §6 (phase-4 note)
6
+ - Supersedes: none — extends ADR 0006's core invariant ("never evict without
7
+ explicit operator confirmation") to the request-driven case.
8
+
9
+ ## Context
10
+
11
+ Placement is request-driven: a gated request that parks because its
12
+ model is not resident can load itself, so the operator stops running
13
+ `uap models apply` by hand (the motivating case: running `ugc-factory`
14
+ end-to-end without manual model switching). The spec's phase table originally
15
+ said phase 4 ships "auto-load alongside; never displacement", and the core
16
+ invariant says an operator confirms every eviction. On this machine
17
+ `load_alongside` has no solutions at all (one config holds 21,812 of 24,576
18
+ MiB), so alongside-only auto mode would auto-load nothing that matters here
19
+ and the operator would keep hand-running swaps for exactly the models they
20
+ already trust.
21
+
22
+ ## Decision
23
+
24
+ 1. **Non-displacing options auto-enforce whenever the policy is enabled**
25
+ (`~/.uap/placement-auto.json`, opt-in, fail-closed). Reuse needs nothing;
26
+ load-alongside evicts nothing; the budget math already said it fits.
27
+ 2. **Displacement auto-enforces only for models on an explicit allowlist**,
28
+ recorded by `uap models auto --allow-displace <model> --yes`. The allowlist
29
+ IS the explicit operator confirmation the core invariant requires:
30
+ - standing, not per-event — the `--yes` gate prints exactly what is being
31
+ consented to ("UNLOADS the current resident(s) — the minimal set that
32
+ makes room, re-evaluated at load time — and loads the requested one
33
+ WITHOUT an operator prompt between them");
34
+ - deliberate — nothing enters it by default, and a bare `--allow-displace`
35
+ without `--yes` records nothing;
36
+ - auditable and revocable — the file is plain JSON in `~/.uap`, per-model
37
+ removal via `--disallow-displace`, whole feature off via `--disable`.
38
+ 3. **The consent subject is the model being LOADED, not the victim.** Victims
39
+ are dynamic: enforcement re-derives the minimal eviction set and
40
+ drift-checks it against the live ledger at run time (`enforce.ts`), so a
41
+ static victim list would go stale the moment residents change. The loaded
42
+ model is the stable thing the operator is vouching for.
43
+ 4. **Run-shape guards bound the standing consent** (phase-4 parallel review):
44
+ one run per requested model, single-flight machine-wide, a hard concurrency
45
+ cap, a failure cooldown that kills any drain→stop→fail→rollback
46
+ oscillation, TTL extension so the supervised entry outlives its run, and a
47
+ run that never rejects (a ledger-write throw must not kill the dashboard).
48
+
49
+ ## Consequences
50
+
51
+ - The operator's machines can swap models unattended, but only for models
52
+ they explicitly named; everything else still parks for a human `apply`.
53
+ - The allowlist must be reviewed like any standing credential: a model on it
54
+ can be loaded by any gated client request while the resident is evicted
55
+ without a prompt. `uap models auto` (status) is the audit surface.
56
+ - "Never displacement" in the phase table was amended to "never displacement
57
+ by default" — the reasoning lives in the spec §6 phase-4 note and here.
58
+ - The proxy stays dumb (reason strings only); the controller remains the
59
+ single decision-maker, and the policy file is the single authority
60
+ (independent of `PROXY_PLACEMENT_MODE`).
61
+
62
+ ## Addendum (2026-10-11): idle unload uses the same doctrine
63
+
64
+ Auto-load had no reverse: residents loaded by §4.4.1 held their device until
65
+ a human stopped them. The idle sweep (spec §4.4.2) extends this ADR's
66
+ reasoning to auto-UNLOAD, which is also an unattended change to what runs on
67
+ the machine:
68
+
69
+ - `unload_allow` is standing consent with the same shape as
70
+ `allow_displace`: `uap models auto --allow-unload <model> --yes` (the
71
+ `--yes` gate prints what stops, when), per-model revocation via
72
+ `--disallow-unload`, feature off with no `unload_idle_after_secs` recorded.
73
+ - The consent subject is again the model, not the moment: the clock resets on
74
+ every gated request served, an unwatched resident's clock starts at first
75
+ observation (arming never evicts the already-idle), and unknown endpoint
76
+ state (`ss` unable to answer) is a refusal to unload, never a guess.
77
+ - The stop reuses the operator's full `unloadPlacement` machinery — the
78
+ standing consent covers WHEN, and the drain/in-flight/rollback guards
79
+ still bound it per-event.