Merge branch 'master' into NLPCRAFT-384
diff --git a/nlpcraft-examples/alarm/pom.xml b/nlpcraft-examples/alarm/pom.xml
index 9856392..9420959 100644
--- a/nlpcraft-examples/alarm/pom.xml
+++ b/nlpcraft-examples/alarm/pom.xml
@@ -25,8 +25,8 @@
     <artifactId>nlpcraft-example-alarm</artifactId>
 
     <parent>
-        <artifactId>nlpcraft-parent</artifactId>
         <groupId>org.apache.nlpcraft</groupId>
+        <artifactId>nlpcraft-parent</artifactId>
         <version>0.9.0</version>
         <relativePath>../../pom.xml</relativePath>
     </parent>
@@ -70,6 +70,7 @@
                     <target>${java.ver}</target>
                 </configuration>
             </plugin>
+
             <plugin>
                 <groupId>com.bazaarvoice.maven.plugins</groupId>
                 <artifactId>process-exec-maven-plugin</artifactId>
diff --git a/nlpcraft-examples/alarm/src/main/java/org/apache/nlpcraft/examples/alarm/AlarmModel.java b/nlpcraft-examples/alarm/src/main/java/org/apache/nlpcraft/examples/alarm/AlarmModel.java
index 0e15a02..a6034a7 100644
--- a/nlpcraft-examples/alarm/src/main/java/org/apache/nlpcraft/examples/alarm/AlarmModel.java
+++ b/nlpcraft-examples/alarm/src/main/java/org/apache/nlpcraft/examples/alarm/AlarmModel.java
@@ -62,7 +62,7 @@
      * @param ctx Intent solver context.
      * @return Query result.
      */
-    @NCIntentRef("alarm") // Intent is defined in JSON model file (alarm_model.json and intents.idl).
+    @NCIntentRef("alarm") // Intent is defined in JSON model file (alarm_model.json and alarm_intents.idl).
     @NCIntentSampleRef("alarm_samples.txt") // Samples supplied in an external file.
     NCResult onMatch(
         NCIntentMatch ctx,
diff --git a/nlpcraft-examples/alarm/src/main/resources/intents.idl b/nlpcraft-examples/alarm/src/main/resources/alarm_intents.idl
similarity index 89%
rename from nlpcraft-examples/alarm/src/main/resources/intents.idl
rename to nlpcraft-examples/alarm/src/main/resources/alarm_intents.idl
index 3c3934d..b4fdd7b 100644
--- a/nlpcraft-examples/alarm/src/main/resources/intents.idl
+++ b/nlpcraft-examples/alarm/src/main/resources/alarm_intents.idl
@@ -15,13 +15,17 @@
  * limitations under the License.
  */
 
+/*
+ * Read documentation: http://nlpcraft.apache.org/intent-matching.html
+ */
+
 // Fragments (mostly for demo purposes here).
 fragment=buzz term~{# == 'x:alarm'}
 fragment=when
     term(nums)~{
         // Demonstrating term variables.
         @type = meta_tok('nlpcraft:num:unittype')
-        @iseq = meta_tok('nlpcraft:num:isequalcondition') // Excludes conditional statements.
+        @isEq = meta_tok('nlpcraft:num:isequalcondition') // Excludes conditional statements.
 
         # == 'nlpcraft:num' && @type == 'datetime' && @iseq == true
     }[1,7]
diff --git a/nlpcraft-examples/alarm/src/main/resources/alarm_model.json b/nlpcraft-examples/alarm/src/main/resources/alarm_model.json
index 9060fde..e55fd15 100644
--- a/nlpcraft-examples/alarm/src/main/resources/alarm_model.json
+++ b/nlpcraft-examples/alarm/src/main/resources/alarm_model.json
@@ -34,6 +34,6 @@
         }
     ],
     "intents": [
-        "import('intents.idl')" // Import intents from external file.
+        "import('alarm_intents.idl')" // Import intents from external file.
     ]
 }
\ No newline at end of file
diff --git a/nlpcraft-examples/cargps/README.md b/nlpcraft-examples/cargps/README.md
new file mode 100644
index 0000000..ce7a565
--- /dev/null
+++ b/nlpcraft-examples/cargps/README.md
@@ -0,0 +1,45 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements.  See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<img src="https://nlpcraft.apache.org/images/nlpcraft_logo_black.gif" height="80px" alt="">
+<br>
+
+[![License](https://img.shields.io/badge/license-Apache%202-blue.svg)](https://raw.githubusercontent.com/apache/opennlp/master/LICENSE)
+[![Build](https://github.com/apache/incubator-nlpcraft/workflows/build/badge.svg)](https://github.com/apache/incubator-nlpcraft/actions)
+[![Documentation Status](https://img.shields.io/:docs-latest-green.svg)](https://nlpcraft.apache.org/docs.html)
+[![Gitter](https://badges.gitter.im/apache-nlpcraft/community.svg)](https://gitter.im/apache-nlpcraft/community)
+
+### Car GPS Example
+This example provides a simulation of the in-car GPS-based navigation system with the natural 
+language interface.
+     
+For any questions, feedback or suggestions:
+
+ * View & run other [examples](https://github.com/apache/incubator-nlpcraft/tree/master/nlpcraft-examples)
+ * Read [documentation](https://nlpcraft.apache.org/docs.html), latest [Javadoc](https://nlpcraft.apache.org/apis/latest/index.html) and [REST APIs](https://nlpcraft.apache.org/using-rest.html)
+ * Download & Maven/Grape/Gradle/SBT [instructions](https://nlpcraft.apache.org/download.html)
+ * File a bug or improvement in [JIRA](https://issues.apache.org/jira/projects/NLPCRAFT)
+ * Post a question at [Stack Overflow](https://stackoverflow.com/questions/ask) using <code>nlpcraft</code> tag
+ * Access [GitHub](https://github.com/apache/incubator-nlpcraft) mirror repository.
+ * Join project developers on [dev@nlpcraft.apache.org](mailto:dev-subscribe@nlpcraft.apache.org)
+
+### Copyright
+Copyright (C) 2021 Apache Software Foundation
+
+<img src="https://www.apache.org/img/ASF20thAnniversary.jpg" height="64px" alt="ASF Logo">
+
+
diff --git a/nlpcraft-examples/cargps/pom.xml b/nlpcraft-examples/cargps/pom.xml
new file mode 100644
index 0000000..939d4f3
--- /dev/null
+++ b/nlpcraft-examples/cargps/pom.xml
@@ -0,0 +1,151 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements.  See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <name>NLPCraft Example Car GPS</name>
+    <artifactId>nlpcraft-example-cargps</artifactId>
+
+    <parent>
+        <artifactId>nlpcraft-parent</artifactId>
+        <groupId>org.apache.nlpcraft</groupId>
+        <version>0.9.0</version>
+        <relativePath>../../pom.xml</relativePath>
+    </parent>
+
+    <properties>
+        <nlpcraft.server.module>nlpcraft</nlpcraft.server.module>
+        <nlpcraft.all.deps.jar>apache-${nlpcraft.server.module}-incubating-${project.version}-all-deps.jar</nlpcraft.all.deps.jar>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>nlpcraft</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+        <!-- Test dependencies. -->
+        <dependency>
+            <groupId>org.junit.jupiter</groupId>
+            <artifactId>junit-jupiter-engine</artifactId>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>nlpcraft</artifactId>
+            <version>${project.version}</version>
+            <type>test-jar</type>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <version>${maven.compiler.plugin.ver}</version>
+                <configuration>
+                    <source>${java.ver}</source>
+                    <target>${java.ver}</target>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>com.bazaarvoice.maven.plugins</groupId>
+                <artifactId>process-exec-maven-plugin</artifactId>
+                <version>${maven.bazaarvoice.plugin.ver}</version>
+                <executions>
+                    <execution>
+                        <id>pre-integration-test</id>
+                        <phase>pre-integration-test</phase>
+                        <goals>
+                            <goal>start</goal>
+                        </goals>
+                        <configuration>
+                            <!--
+                                Depending on the console config and how maven is run this will produce the output with ANSI colors.
+                                To strip out ANSI escape sequences from the log file, see the following:
+                                https://stackoverflow.com/questions/17998978/removing-colors-from-output
+                            -->
+                            <name>server</name>
+                            <healthcheckUrl>http://localhost:8081/api/v1/health</healthcheckUrl>
+                            <waitAfterLaunch>600</waitAfterLaunch>
+                            <processLogFile>${project.build.directory}/server-${timestamp}.log</processLogFile>
+                            <arguments>
+                                <argument>${java.home}/bin/java</argument>
+                                <argument>-Xmx4G</argument>
+                                <argument>-Xms4G</argument>
+                                <argument>--add-exports=java.base/jdk.internal.misc=ALL-UNNAMED</argument>
+                                <argument>--add-exports=java.base/sun.nio.ch=ALL-UNNAMED</argument>
+                                <argument>--add-exports=java.management/com.sun.jmx.mbeanserver=ALL-UNNAMED</argument>
+                                <argument>--add-exports=jdk.internal.jvmstat/sun.jvmstat.monitor=ALL-UNNAMED</argument>
+                                <argument>--add-exports=java.base/sun.reflect.generics.reflectiveObjects=ALL-UNNAMED</argument>
+                                <argument>--add-opens=jdk.management/com.sun.management.internal=ALL-UNNAMED</argument>
+                                <argument>--illegal-access=permit</argument>
+                                <argument>-DNLPCRAFT_ANSI_COLOR_DISABLED=true</argument> <!-- Remove ANSI at least from NLPCraft output. -->
+                                <argument>-Djdk.tls.client.protocols=TLSv1.2</argument>
+                                <argument>-jar</argument>
+                                <argument>${project.basedir}/../../${nlpcraft.server.module}/target/${nlpcraft.all.deps.jar}</argument>
+                                <argument>-server</argument>
+                            </arguments>
+                        </configuration>
+                    </execution>
+                    <execution>
+                        <id>stop-all</id>
+                        <phase>post-integration-test</phase>
+                        <goals>
+                            <goal>stop-all</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-surefire-plugin</artifactId>
+                <version>${maven.surefire.plugin.ver}</version>
+                <configuration>
+                    <!-- Skips all tests on phase `test`. -->
+                    <skip>true</skip>
+                </configuration>
+                <executions>
+                    <!-- All tests are defined as integration. -->
+                    <execution>
+                        <id>integration-tests</id>
+                        <phase>integration-test</phase>
+                        <goals>
+                            <goal>test</goal>
+                        </goals>
+                        <configuration>
+                            <skip>false</skip>
+                            <!-- Mandatory part. -->
+                            <includes>
+                                <include>**/*.*</include>
+                            </includes>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+</project>
\ No newline at end of file
diff --git a/nlpcraft-examples/cargps/src/main/java/org/apache/nlpcraft/examples/cargps/CarGpsModel.scala b/nlpcraft-examples/cargps/src/main/java/org/apache/nlpcraft/examples/cargps/CarGpsModel.scala
new file mode 100644
index 0000000..9b6cf41
--- /dev/null
+++ b/nlpcraft-examples/cargps/src/main/java/org/apache/nlpcraft/examples/cargps/CarGpsModel.scala
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.nlpcraft.examples.cargps
+
+import org.apache.nlpcraft.model._
+
+/**
+ * See 'README.md' file in the same folder for running and testing instructions.
+ */
+class CarGpsModel extends NCModelFileAdapter("cargps_model.yaml") {
+    /**
+     *
+     * @return
+     */
+    @NCIntentRef("int:navigate")
+    @NCIntentSampleRef("samples/cargps_navigate_samples.txt")
+    def onNavigation(): NCResult = {
+        NCResult.text(s"")
+    }
+
+    /**
+     *
+     * @return
+     */
+    @NCIntentRef("int:cancel")
+    @NCIntentSampleRef("samples/cargps_cancel_samples.txt")
+    def onCancel(): NCResult = {
+        NCResult.text(s"")
+    }
+
+    /**
+     *
+     * @return
+     */
+    @NCIntentRef("int:add:waypoint")
+    @NCIntentSampleRef("samples/cargps_add_waypoint_samples.txt")
+    def onAddWaypoint(): NCResult = {
+        NCResult.text(s"")
+    }
+
+    /**
+     *
+     * @return
+     */
+    @NCIntentRef("int:remove:waypoint")
+    @NCIntentSampleRef("samples/cargps_remove_waypoint_samples.txt")
+    def onRemoveWaypoint(): NCResult = {
+        NCResult.text(s"")
+    }
+}
diff --git a/nlpcraft-examples/cargps/src/main/resources/cargps_intents.idl b/nlpcraft-examples/cargps/src/main/resources/cargps_intents.idl
new file mode 100644
index 0000000..bf82b2c
--- /dev/null
+++ b/nlpcraft-examples/cargps/src/main/resources/cargps_intents.idl
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+ /*
+  * Read documentation: http://nlpcraft.apache.org/intent-matching.html
+  */
+
+// Reusable fragments.
+fragment=hey term={tok_id() == "x:hey" && tok_is_first()}
+
+// Intents.
+intent=int:cancel
+    // Ignore any other user or system tokens if we found 'cancel' token.
+    options={'unused_usr_toks': true, 'unused_sys_toks': true}
+    fragment(hey)
+    term={tok_id() == "x:cancel"}
+
+intent=int:navigate fragment(hey) term={tok_id() == "x:navigate"} term={tok_id() == "x:addr"}
+intent=int:add:waypoint fragment(hey) term={tok_id() == "x:add-waypoint"}
+intent=int:remove:waypoint fragment(hey) term={tok_id() == "x:remove-waypoint"}
\ No newline at end of file
diff --git a/nlpcraft-examples/cargps/src/main/resources/cargps_model.yaml b/nlpcraft-examples/cargps/src/main/resources/cargps_model.yaml
new file mode 100644
index 0000000..8f8bde7
--- /dev/null
+++ b/nlpcraft-examples/cargps/src/main/resources/cargps_model.yaml
@@ -0,0 +1,90 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+id: "nlpcraft.cargps.ex"
+name: "Car GPS Example Model"
+version: "1.0"
+description: "NLI-powered car GPS-based navigation example model."
+enabledBuiltInTokens:
+    - "nlpcraft:num"
+    - "nlpcraft:city"
+    - "nlpcraft:country"
+    - "nlpcraft:region"
+
+macros:
+  - name: "<HEY>"
+    macro: "{hey|hi|howdy}"
+  - name: "<NAVIGATE>"
+    macro: "{navigate|pilot|plot|drive|route|plan|find|head|ride|direct|steer|operate|sail} {out|_} {course|route|destination|drive|_}"
+  - name: "<CANCEL>"
+    macro: "{cancel|stop|abort|finish|cease|quit} {off|_}"
+  - name: "<WAYPOINT>"
+    macro: "{waypoint|location|point|stopover|stop over|way station|stop|checkpoint|stop point} {point|station|_}"
+
+abstractTokens:
+  - x:addr:kind
+  - x:addr:num
+  - x:addr:st
+
+elements:
+  - id: "x:addr:kind"
+    # Short list from https://pe.usps.com/text/pub28/28apc_002.htm
+    synonyms:
+      # street[0,2] => {_|street|street street}
+      - "{street|drive|court|plaza|avenue|alley|anex|beach|bend|boulevard|bridge|canyon|causeway|way|circle|corner|creek|fork|harbor|highway|expressway|island|lane|lake|loop|motorway|park|path|point|ramp|route|rue|row|skyway|square|station|summit|trail|tunnel|walk|road}"
+      - "{st|str|dr|crt|plz|ave|blvd|hwy|rd}"
+
+  - id: "x:addr:num"
+    synonyms:
+      - "^^{tok_id() == 'nlpcraft:num' && meta_tok('nlpcraft:num:unit') == null && meta_tok('nlpcraft:num:isequalcondition')}^^"
+
+  - id: "x:addr:st"
+    synonyms:
+      - "{//[a-zA-Z0-9]+//}[1,3]"
+
+  - id: "x:addr"
+    synonyms:
+      - "^^[num]{tok_id() == 'x:addr:num'}^^ ^^[name]{tok_id() == 'x:addr:st'}^^ ^^[kind]{tok_id() == 'x:addr:kind'}^^"
+
+  - id: "x:hey"
+    description: "NLI prompt"
+    synonyms:
+      - "<HEY> {car|vehicle|truck}"
+
+  - id: "x:cancel"
+    description: "Cancel action."
+    synonyms:
+      - "<CANCEL>"
+
+  - id: "x:navigate"
+    description: "Start 'navigate' action."
+    synonyms:
+      - "<NAVIGATE>"
+
+  - id: "x:add-waypoint"
+    description: "Add 'waypoint' action."
+    synonyms:
+      - "{add|make} <WAYPOINT>"
+      - "stop by"
+
+  - id: "x:remove-waypoint"
+    description: "Remove 'waypoint' action."
+    synonyms:
+      - "{skip|remove} {over|_} {last|latest|_} <WAYPOINT>"
+
+intents:
+  - "import('cargps_intents.idl')"
\ No newline at end of file
diff --git a/nlpcraft-examples/cargps/src/main/resources/probe.conf b/nlpcraft-examples/cargps/src/main/resources/probe.conf
new file mode 100644
index 0000000..e15ac80
--- /dev/null
+++ b/nlpcraft-examples/cargps/src/main/resources/probe.conf
@@ -0,0 +1,148 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+#
+# This is joint configuration file for both the server and the data probes. Note that
+# server and probe configuration can be placed into separate files - each file containing only
+# 'nlpcraft.server' or 'nlpcraft.probe' sub-sections.
+#
+# You can also provide configuration properties or override the default ones via environment variables.
+# To use environment variables override:
+# 1. Set probe or server JVM system property -Dconfig.override_with_env_vars=true
+# 2. For each configuration 'x.y.z' set the environment variable CONFIG_FORCE_x_y_z=some_value
+#
+# Examples of environment variables:
+#   -- Overrides 'nlpcraft.sever.host' configuration property.
+#   CONFIG_FORCE_nlpcraft_server_rest_host="localhost"
+#
+#   -- Overrides 'nlpcraft.sever.models' configuration property.
+#   CONFIG_FORCE_nlpcraft_server_models="com.models.MyModel"
+#
+# See https://nlpcraft.apache.org/server-and-probe.html for more details.
+#
+
+# Common server/probe configuration root.
+nlpcraft {
+    # Basic NLP toolkit to use on both server and probes. Possible values:
+    # - 'opennlp'
+    # - 'stanford'
+    #
+    # NOTE: Stanford CoreNLP requires special installation due to its licensing.
+    # See https://nlpcraft.apache.org/integrations.html#stanford for more details.
+    nlpEngine = "opennlp"
+
+    # External configuration resources.
+    #
+    # NOTE:
+    # ----
+    # Due to licensing restrictions of the official ASF release policy some of the
+    # configuration for NLPCraft cannot be shipped with the official Apache release.
+    # Instead, NLPCraft will attempt to download these configuration files from the
+    # external URL upon the first start.
+    #
+    # NLPCraft will attempt to download the missing configuration files from URL defined
+    # in 'nlpcraft.extConfig.extUrl' property and place them into 'nlpcraft.extConfig.locDir'
+    # folder on the local file system. On subsequent starts, NLPCraft will check if the required
+    # file is already present locally and skip the download in such case. If 'nlpcraft.extConfig.checkMd5'
+    # property is set to 'true' then on each start NLPCraft will check the checksum of each file
+    # locally and remote and will re-download such file if the MD5 checksums don't match.
+    #
+    # By default, the external configuration is stored in the main Git repository for NLPCraft
+    # project from where it will be downloaded ('/external' folder). See this folder in the Git
+    # repository for more information: https://github.com/apache/incubator-nlpcraft/raw/external_config/external
+    extConfig {
+        # Mandatory.
+        extUrl = "https://github.com/apache/incubator-nlpcraft/raw/external_config/external"
+
+        # Optional.
+        # Default value is $USER_HOME/.nlpcraft/extcfg
+        # locDir = ...
+
+        # If 'true', on each start NLPCraft will check the MD5 checksum of the each local and remote
+        # external configuration file and will re-download such file if the checksum doesn't match.
+        # Set it to 'false' to speed up the bootstrap of the NLPCraft server and the data probe if you
+        # are certain that all external configuration files are properly downloaded and available
+        # in 'nlpcraft.extConfig.locDir' local folder.
+        checkMd5 = true
+    }
+
+    # +---------------------+
+    # | Probe configuration. |
+    # +---------------------+
+    probe {
+        # Any arbitrary descriptive name.
+        id = "cargps"
+
+        # This is the default token (as in default company).
+        # Note that this token must match the probe token for the company this probe
+        # associated with. If changed from default, this token must be kept secure.
+        token = "3141592653589793"
+
+        # These are default up-link and down-link endpoints that the probe will connect to.
+        # If changed - they need to be changed on both server and probe.
+        upLink = "0.0.0.0:8201"   # Server to probe data pipe.
+        downLink = "0.0.0.0:8202" # Probe to server data pipe.
+
+        # All JARs in this folder will be scanned for models.
+        # Safely ignored if 'null' - but then 'models' should have at least one element.
+        jarsFolder = null
+
+        # Specifies fully qualifies model class names for the probe to start with.
+        #
+        # Note that following models require 'google' on the server side.
+        # See https://nlpcraft.apache.org/integrations.html#nlp for more details
+        # on how to configure 3rd party token providers:
+        models = org.apache.nlpcraft.examples.cargps.CarGpsModel
+
+        # Specify class names for probe life cycle components.
+        # Each class should extend 'NCProbeLifecycle' interface and provide a no-arg constructor.
+        #
+        # The following built-in OpenCensus exporters are supported as lifecycle components:
+        # - org.apache.nlpcraft.model.opencensus.NCJaegerExporter (traces)
+        # - org.apache.nlpcraft.model.opencensus.NCZipkinExporter (traces)
+        # - org.apache.nlpcraft.model.opencensus.NCPrometheusExporter (stats)
+        # - org.apache.nlpcraft.model.opencensus.NCStackdriverTraceExporter (traces)
+        # - org.apache.nlpcraft.model.opencensus.NCStackdriverStatsExporter (stats)
+        lifecycle = ""
+
+        # Properties for built-in OpenCensus exporters.
+        # All configuration properties are optional unless otherwise specified.
+        # opencensus {
+        #     jaeger {
+        #         thriftUrl = "http://127.0.0.1:14268/api/traces"
+        #         serviceName = "nlpcraft-probe"
+        #     }
+        #     prometheus {
+        #         hostPort = "localhost:8889"
+        #         namespace = "nlpcraft-probe"
+        #     }
+        #     stackdriver {
+        #         # Mandatory Google project ID.
+        #         googleProjectId = "your_google_project_id"
+        #         metricsPrefix = "custom.googleapis.com/nlpcraft/probe"
+        #     }
+        #     zipkin {
+        #         v2Url = "http://127.0.0.1:9411/api/v2/spans"
+        #         serviceName = "nlpcraft-probe"
+        #     }
+        # }
+
+        # Maximum execution result size in bytes. Default value is 1M.
+        # When exceeded the request will be automatically rejected.
+        resultMaxSizeBytes = 1048576
+    }
+}
diff --git a/nlpcraft-examples/cargps/src/main/resources/samples/cargps_add_waypoint_samples.txt b/nlpcraft-examples/cargps/src/main/resources/samples/cargps_add_waypoint_samples.txt
new file mode 100644
index 0000000..4c3f520
--- /dev/null
+++ b/nlpcraft-examples/cargps/src/main/resources/samples/cargps_add_waypoint_samples.txt
@@ -0,0 +1,21 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+#
+# Set of samples (corpus) for automatic unit and regression testing.
+#
+
diff --git a/nlpcraft-examples/cargps/src/main/resources/samples/cargps_cancel_samples.txt b/nlpcraft-examples/cargps/src/main/resources/samples/cargps_cancel_samples.txt
new file mode 100644
index 0000000..c6b132d
--- /dev/null
+++ b/nlpcraft-examples/cargps/src/main/resources/samples/cargps_cancel_samples.txt
@@ -0,0 +1,28 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+#
+# Set of samples (corpus) for automatic unit and regression testing.
+#
+
+Hey truck - stop the navigation!
+Howdy, car, please cancel the routing now.
+Hi car - stop the route.
+Hi car - stop the navigation...
+Howdy truck - quit navigating.
+Hi car - finish off the driving.
+Hi car - cancel the journey.
\ No newline at end of file
diff --git a/nlpcraft-examples/cargps/src/main/resources/samples/cargps_navigate_samples.txt b/nlpcraft-examples/cargps/src/main/resources/samples/cargps_navigate_samples.txt
new file mode 100644
index 0000000..029340e
--- /dev/null
+++ b/nlpcraft-examples/cargps/src/main/resources/samples/cargps_navigate_samples.txt
@@ -0,0 +1,21 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+#
+# Set of samples (corpus) for automatic unit and regression testing.
+#
+hey car, navigate to 21 table rock drive
diff --git a/nlpcraft-examples/cargps/src/main/resources/samples/cargps_remove_waypoint_samples.txt b/nlpcraft-examples/cargps/src/main/resources/samples/cargps_remove_waypoint_samples.txt
new file mode 100644
index 0000000..4c3f520
--- /dev/null
+++ b/nlpcraft-examples/cargps/src/main/resources/samples/cargps_remove_waypoint_samples.txt
@@ -0,0 +1,21 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+#
+# Set of samples (corpus) for automatic unit and regression testing.
+#
+
diff --git a/nlpcraft-examples/alarm/src/main/resources/intents.idl b/nlpcraft-examples/cargps/src/test/java/org/apache/nlpcraft/examples/cargps/NCCarGpsModelSpec.scala
similarity index 63%
copy from nlpcraft-examples/alarm/src/main/resources/intents.idl
copy to nlpcraft-examples/cargps/src/test/java/org/apache/nlpcraft/examples/cargps/NCCarGpsModelSpec.scala
index 3c3934d..2e90850 100644
--- a/nlpcraft-examples/alarm/src/main/resources/intents.idl
+++ b/nlpcraft-examples/cargps/src/test/java/org/apache/nlpcraft/examples/cargps/NCCarGpsModelSpec.scala
@@ -15,18 +15,15 @@
  * limitations under the License.
  */
 
-// Fragments (mostly for demo purposes here).
-fragment=buzz term~{# == 'x:alarm'}
-fragment=when
-    term(nums)~{
-        // Demonstrating term variables.
-        @type = meta_tok('nlpcraft:num:unittype')
-        @iseq = meta_tok('nlpcraft:num:isequalcondition') // Excludes conditional statements.
+package org.apache.nlpcraft.examples.cargps
 
-        # == 'nlpcraft:num' && @type == 'datetime' && @iseq == true
-    }[1,7]
+import org.apache.nlpcraft.{NCTestContext, NCTestEnvironment}
+import org.junit.jupiter.api.Test
 
-// Intents (using fragments).
-intent=alarm
-    fragment(buzz)
-    fragment(when)
\ No newline at end of file
+@NCTestEnvironment(model = classOf[CarGpsModel], startClient = true)
+class NCCarGpsModelSpec extends NCTestContext {
+    @Test
+    def test(): Unit = {
+        checkIntent("21 x x drive", "int:navigate")
+    }
+}
diff --git a/nlpcraft-examples/minecraft/src/test/kotlin/org/apache/nlpcraft/example/minecraft/NCModelValidationSpec.scala b/nlpcraft-examples/cargps/src/test/java/org/apache/nlpcraft/examples/cargps/NCModelValidationSpec.scala
similarity index 93%
copy from nlpcraft-examples/minecraft/src/test/kotlin/org/apache/nlpcraft/example/minecraft/NCModelValidationSpec.scala
copy to nlpcraft-examples/cargps/src/test/java/org/apache/nlpcraft/examples/cargps/NCModelValidationSpec.scala
index f1b572e..e46e10a 100644
--- a/nlpcraft-examples/minecraft/src/test/kotlin/org/apache/nlpcraft/example/minecraft/NCModelValidationSpec.scala
+++ b/nlpcraft-examples/cargps/src/test/java/org/apache/nlpcraft/examples/cargps/NCModelValidationSpec.scala
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.nlpcraft.example.minecraft
+package org.apache.nlpcraft.examples.cargps
 
 import org.apache.nlpcraft.model.tools.test.NCTestAutoModelValidator
 import org.junit.jupiter.api.{Assertions, Test}
@@ -27,7 +27,7 @@
     @Test
     def test(): Unit = {
         // Instruct auto-validator what models to test.
-        System.setProperty("NLPCRAFT_TEST_MODELS", "org.apache.nlpcraft.example.minecraft.MinecraftModel")
+        System.setProperty("NLPCRAFT_TEST_MODELS", "org.apache.nlpcraft.examples.cargps.CarGpsModel")
 
         // Start model auto-validator.
         Assertions.assertTrue(NCTestAutoModelValidator.isValid(),"See error logs above.")
diff --git a/nlpcraft-examples/minecraft/pom.xml b/nlpcraft-examples/minecraft/pom.xml
index 09ee22a..69c3d40 100644
--- a/nlpcraft-examples/minecraft/pom.xml
+++ b/nlpcraft-examples/minecraft/pom.xml
@@ -21,7 +21,7 @@
          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     <modelVersion>4.0.0</modelVersion>
 
-    <name>NLPCraft example Minecraft</name>
+    <name>NLPCraft Example Minecraft</name>
     <artifactId>nlpcraft-example-minecraft</artifactId>
 
     <parent>
diff --git a/nlpcraft-examples/minecraft/src/main/kotlin/org/apache/nlpcraft/example/minecraft/MinecraftFillMatchProcessor.kt b/nlpcraft-examples/minecraft/src/main/kotlin/org/apache/nlpcraft/examples/minecraft/MinecraftFillMatchProcessor.kt
similarity index 96%
rename from nlpcraft-examples/minecraft/src/main/kotlin/org/apache/nlpcraft/example/minecraft/MinecraftFillMatchProcessor.kt
rename to nlpcraft-examples/minecraft/src/main/kotlin/org/apache/nlpcraft/examples/minecraft/MinecraftFillMatchProcessor.kt
index 75790e1..779d7d2 100644
--- a/nlpcraft-examples/minecraft/src/main/kotlin/org/apache/nlpcraft/example/minecraft/MinecraftFillMatchProcessor.kt
+++ b/nlpcraft-examples/minecraft/src/main/kotlin/org/apache/nlpcraft/examples/minecraft/MinecraftFillMatchProcessor.kt
@@ -16,9 +16,9 @@
  *
  */
 
-package org.apache.nlpcraft.example.minecraft
+package org.apache.nlpcraft.examples.minecraft
 
-import org.apache.nlpcraft.example.minecraft.MinecraftValueLoader.Companion.dumps
+import org.apache.nlpcraft.examples.minecraft.MinecraftValueLoader.Companion.dumps
 import org.apache.nlpcraft.model.*
 import java.util.*
 
diff --git a/nlpcraft-examples/minecraft/src/main/kotlin/org/apache/nlpcraft/example/minecraft/MinecraftModel.kt b/nlpcraft-examples/minecraft/src/main/kotlin/org/apache/nlpcraft/examples/minecraft/MinecraftModel.kt
similarity index 96%
rename from nlpcraft-examples/minecraft/src/main/kotlin/org/apache/nlpcraft/example/minecraft/MinecraftModel.kt
rename to nlpcraft-examples/minecraft/src/main/kotlin/org/apache/nlpcraft/examples/minecraft/MinecraftModel.kt
index 954ab40..de96e25 100644
--- a/nlpcraft-examples/minecraft/src/main/kotlin/org/apache/nlpcraft/example/minecraft/MinecraftModel.kt
+++ b/nlpcraft-examples/minecraft/src/main/kotlin/org/apache/nlpcraft/examples/minecraft/MinecraftModel.kt
@@ -16,10 +16,10 @@
  *
  */
 
-package org.apache.nlpcraft.example.minecraft
+package org.apache.nlpcraft.examples.minecraft
 
 import org.apache.nlpcraft.common.NCException
-import org.apache.nlpcraft.example.minecraft.MinecraftValueLoader.Companion.dumps
+import org.apache.nlpcraft.examples.minecraft.MinecraftValueLoader.Companion.dumps
 import org.apache.nlpcraft.model.*
 import java.util.*
 
diff --git a/nlpcraft-examples/minecraft/src/main/kotlin/org/apache/nlpcraft/example/minecraft/MinecraftValueLoader.kt b/nlpcraft-examples/minecraft/src/main/kotlin/org/apache/nlpcraft/examples/minecraft/MinecraftValueLoader.kt
similarity index 97%
rename from nlpcraft-examples/minecraft/src/main/kotlin/org/apache/nlpcraft/example/minecraft/MinecraftValueLoader.kt
rename to nlpcraft-examples/minecraft/src/main/kotlin/org/apache/nlpcraft/examples/minecraft/MinecraftValueLoader.kt
index 429adcf..2b658f4 100644
--- a/nlpcraft-examples/minecraft/src/main/kotlin/org/apache/nlpcraft/example/minecraft/MinecraftValueLoader.kt
+++ b/nlpcraft-examples/minecraft/src/main/kotlin/org/apache/nlpcraft/examples/minecraft/MinecraftValueLoader.kt
@@ -16,7 +16,7 @@
  *
  */
 
-package org.apache.nlpcraft.example.minecraft
+package org.apache.nlpcraft.examples.minecraft
 
 import com.fasterxml.jackson.core.JsonParser
 import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
diff --git a/nlpcraft-examples/minecraft/src/test/kotlin/org/apache/nlpcraft/example/minecraft/NCMinecraftModelSpec.kt b/nlpcraft-examples/minecraft/src/test/kotlin/org/apache/nlpcraft/examples/minecraft/NCMinecraftModelSpec.kt
similarity index 96%
rename from nlpcraft-examples/minecraft/src/test/kotlin/org/apache/nlpcraft/example/minecraft/NCMinecraftModelSpec.kt
rename to nlpcraft-examples/minecraft/src/test/kotlin/org/apache/nlpcraft/examples/minecraft/NCMinecraftModelSpec.kt
index 811df6b..49f5e56 100644
--- a/nlpcraft-examples/minecraft/src/test/kotlin/org/apache/nlpcraft/example/minecraft/NCMinecraftModelSpec.kt
+++ b/nlpcraft-examples/minecraft/src/test/kotlin/org/apache/nlpcraft/examples/minecraft/NCMinecraftModelSpec.kt
@@ -16,7 +16,7 @@
  *
  */
 
-package org.apache.nlpcraft.example.minecraft
+package org.apache.nlpcraft.examples.minecraft
 
 import org.apache.nlpcraft.NCTestContext
 import org.apache.nlpcraft.NCTestEnvironment
diff --git a/nlpcraft-examples/minecraft/src/test/kotlin/org/apache/nlpcraft/example/minecraft/NCModelValidationSpec.scala b/nlpcraft-examples/minecraft/src/test/kotlin/org/apache/nlpcraft/examples/minecraft/NCModelValidationSpec.scala
similarity index 96%
rename from nlpcraft-examples/minecraft/src/test/kotlin/org/apache/nlpcraft/example/minecraft/NCModelValidationSpec.scala
rename to nlpcraft-examples/minecraft/src/test/kotlin/org/apache/nlpcraft/examples/minecraft/NCModelValidationSpec.scala
index f1b572e..ec9fd03 100644
--- a/nlpcraft-examples/minecraft/src/test/kotlin/org/apache/nlpcraft/example/minecraft/NCModelValidationSpec.scala
+++ b/nlpcraft-examples/minecraft/src/test/kotlin/org/apache/nlpcraft/examples/minecraft/NCModelValidationSpec.scala
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.nlpcraft.example.minecraft
+package org.apache.nlpcraft.examples.minecraft
 
 import org.apache.nlpcraft.model.tools.test.NCTestAutoModelValidator
 import org.junit.jupiter.api.{Assertions, Test}
diff --git a/nlpcraft-examples/time/pom.xml b/nlpcraft-examples/time/pom.xml
index 88c25e2..8da109e 100644
--- a/nlpcraft-examples/time/pom.xml
+++ b/nlpcraft-examples/time/pom.xml
@@ -21,7 +21,7 @@
          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     <modelVersion>4.0.0</modelVersion>
 
-    <name>NLPCraft example Time</name>
+    <name>NLPCraft Example Time</name>
     <artifactId>nlpcraft-example-time</artifactId>
 
     <parent>
diff --git a/nlpcraft/src/main/scala/org/apache/nlpcraft/model/NCCustomParser.java b/nlpcraft/src/main/scala/org/apache/nlpcraft/model/NCCustomParser.java
index 28d0aec..91a3db3 100644
--- a/nlpcraft/src/main/scala/org/apache/nlpcraft/model/NCCustomParser.java
+++ b/nlpcraft/src/main/scala/org/apache/nlpcraft/model/NCCustomParser.java
@@ -37,7 +37,7 @@
      * Analyses user input provided as a list of {@link NCCustomWord} objects and returns a list
      * of {@link NCCustomElement} objects. Note that model elements returned from this method must
      * be defined in the model, i.e. this method only provides an additional logic of detecting these
-     * elements but they still need to be defined normally in the model.
+     * elements, but they still need to be defined normally in the model.
      *
      * @param req User request descriptor.
      * @param mdl Instance of data model this parser belongs to.
diff --git a/nlpcraft/src/main/scala/org/apache/nlpcraft/model/intent/compiler/NCIdlCompiler.scala b/nlpcraft/src/main/scala/org/apache/nlpcraft/model/intent/compiler/NCIdlCompiler.scala
index bf3888d..a3f876a 100644
--- a/nlpcraft/src/main/scala/org/apache/nlpcraft/model/intent/compiler/NCIdlCompiler.scala
+++ b/nlpcraft/src/main/scala/org/apache/nlpcraft/model/intent/compiler/NCIdlCompiler.scala
@@ -633,8 +633,14 @@
             line: Int, // 1, 2, ...
             charPos: Int, // 1, 2, ...
             msg: String,
-            e: RecognitionException): Unit =
-            throw new NCE(mkSyntaxError(msg, recog.getInputStream.getSourceName, line, charPos - 1, dsl, origin, mdl))
+            e: RecognitionException): Unit = {
+            val aMsg = if ((msg.contains("'\"") && msg.contains("\"'")) || msg.contains("''"))
+                s"${if (msg.last == '.') msg.substring(0, msg.length - 1) else msg} - try removing quotes."
+            else
+                msg
+
+            throw new NCE(mkSyntaxError(aMsg, recog.getInputStream.getSourceName, line, charPos - 1, dsl, origin, mdl))
+        }
     }
 
     /**
diff --git a/nlpcraft/src/main/scala/org/apache/nlpcraft/model/intent/solver/NCIntentSolver.scala b/nlpcraft/src/main/scala/org/apache/nlpcraft/model/intent/solver/NCIntentSolver.scala
index 88af005..573ac4c 100644
--- a/nlpcraft/src/main/scala/org/apache/nlpcraft/model/intent/solver/NCIntentSolver.scala
+++ b/nlpcraft/src/main/scala/org/apache/nlpcraft/model/intent/solver/NCIntentSolver.scala
@@ -20,6 +20,7 @@
 import com.typesafe.scalalogging.LazyLogging
 import io.opencensus.trace.Span
 import org.apache.nlpcraft.common._
+import org.apache.nlpcraft.common.ansi.NCAnsi._
 import org.apache.nlpcraft.common.debug.NCLogHolder
 import org.apache.nlpcraft.common.opencensus.NCOpenCensusTrace
 import org.apache.nlpcraft.common.util.NCUtils
@@ -145,7 +146,7 @@
                 if (cbRes.getIntentId == null)
                     cbRes.setIntentId(res.intentId)
                     
-                logger.info(s"Intent '${res.intentId}' for variant #${res.variantIdx + 1} selected as the ${g(bo("<|best match|>"))}.")
+                logger.info(s"Intent ${ansi256Fg(183)}'${res.intentId}'$ansiReset for variant #${res.variantIdx + 1} selected as the ${g(bo("<|best match|>"))}.")
 
                 NCDialogFlowManager.addMatchedIntent(
                     intentMatch,
diff --git a/nlpcraft/src/main/scala/org/apache/nlpcraft/model/intent/solver/NCIntentSolverEngine.scala b/nlpcraft/src/main/scala/org/apache/nlpcraft/model/intent/solver/NCIntentSolverEngine.scala
index 710b9f0..ccff087 100644
--- a/nlpcraft/src/main/scala/org/apache/nlpcraft/model/intent/solver/NCIntentSolverEngine.scala
+++ b/nlpcraft/src/main/scala/org/apache/nlpcraft/model/intent/solver/NCIntentSolverEngine.scala
@@ -37,6 +37,7 @@
  * Intent solver that finds the best matching intent given user sentence.
  */
 object NCIntentSolverEngine extends LazyLogging with NCOpenCensusTrace {
+    private final val DNM = r("did not match")
 
     /**
      * NOTE: not thread-safe.
@@ -352,8 +353,10 @@
 
                 tbl.info(logger, Some(s"Found ${sorted.size} matching ${if (sorted.size > 1) "intents" else "intent"} (sorted $G${BO}best$RST to worst):"))
             }
-            else
-                logger.info("No matching intent found.")
+            else {
+                logger.info(s"No matching intent found:")
+                logger.info(s"  +-- Turn on ${y("DEBUG")} log level to see more details.")
+            }
 
             sorted.map(m =>
                 NCIntentSolverResult(
@@ -437,7 +440,7 @@
             }
 
             if (!flowRegex.get.matcher(str).find(0)) {
-                x(s"${bo(r("did not match"))}")
+                x(DNM)
 
                 flowMatched = false
             }
@@ -470,7 +473,7 @@
             }
 
             if (!res) {
-                x(s"${bo(r("did not match"))}")
+                x(DNM)
 
                 flowMatched = false
             }
@@ -532,12 +535,12 @@
                                 s"${y("<")}${w.head}, ${w(1)}, ${w(2)}, ${w(3)}, ${w(4)}, ${w(5)}${y(">")}"
                             )
 
-                            tbl.info(logger, Some("Term match found:"))
+                            tbl.debug(logger, Some("Term match found:"))
                         }
 
                     case None =>
                         // Term is missing. Stop further processing for this intent. This intent cannot be matched.
-                        logger.info(s"Intent '$intentId' ${bo(r("did not match"))} because of unmatched term '${term.toAnsiString}' $varStr.")
+                        logger.debug(s"Intent '$intentId' $DNM because of unmatched term '${term.toAnsiString}' $varStr.")
 
                         abort = true
                 }
@@ -556,7 +559,7 @@
 
                 if (!opts.allowStmTokenOnly && usedSenToks.isEmpty && usedConvToks.nonEmpty)
                     logger.info(
-                        s"Intent '$intentId' ${bo(r("did not match"))} because all its matched tokens came from STM $varStr. " +
+                        s"Intent '$intentId' $DNM because all its matched tokens came from STM $varStr. " +
                         s"See intent '${c(JSON_ALLOW_STM_ONLY)}' option."
                     )
                 else if (!opts.ignoreUnusedFreeWords && unusedSenToks.exists(_.token.isFreeWord))
@@ -566,7 +569,7 @@
                     info(
                         logger,
                         Some(
-                            s"Intent '$intentId' ${bo(r("did not match"))} because of unused free words $varStr. " +
+                            s"Intent '$intentId' $DNM because of unused free words $varStr. " +
                             s"See intent '${c(JSON_UNUSED_FREE_WORDS)}' option. " +
                             s"Unused free words:"
                         )
@@ -578,7 +581,7 @@
                     info(
                         logger,
                         Some(
-                            s"Intent '$intentId' ${bo(r("did not match"))} because of unused user tokens $varStr. " +
+                            s"Intent '$intentId' $DNM because of unused user tokens $varStr. " +
                             s"See intent '${c(JSON_UNUSED_USR_TOKS)}' option. " +
                             s"Unused user tokens:"
                         )
@@ -590,7 +593,7 @@
                     info(
                         logger,
                         Some(
-                            s"Intent '$intentId' ${bo(r("did not match"))} because of unused system tokens $varStr. " +
+                            s"Intent '$intentId' $DNM because of unused system tokens $varStr. " +
                             s"See intent '${c(JSON_UNUSED_SYS_TOKS)}' option. " +
                             s"Unused system tokens:"
                         )
diff --git a/nlpcraft/src/main/scala/org/apache/nlpcraft/model/tools/cmdline/NCCli.scala b/nlpcraft/src/main/scala/org/apache/nlpcraft/model/tools/cmdline/NCCli.scala
index 1f08d4f..71162db 100644
--- a/nlpcraft/src/main/scala/org/apache/nlpcraft/model/tools/cmdline/NCCli.scala
+++ b/nlpcraft/src/main/scala/org/apache/nlpcraft/model/tools/cmdline/NCCli.scala
@@ -258,13 +258,20 @@
      * @param args
      * @return
      */
-    private def getCpParams(args: Seq[Argument]): String =
-        U.splitTrimFilter(
+    private def getCpParams(args: Seq[Argument]): String = {
+        val s = U.splitTrimFilter(
             getParams( args, "cp").map(cp => normalizeCp(U.trimQuotes(cp))).mkString(CP_SEP),
             CP_SEP
         )
         .mkString(CP_SEP)
 
+        // Remove extra '\' from the end, if possible.
+        if (s.last == '\\' && !s.endsWith(":\\"))
+            s.substring(0, s.length - 1)
+        else
+            s
+    }
+
     /**
      *
      * @param args
@@ -3262,8 +3269,8 @@
             .system(true)
             .nativeSignals(true)
             .signalHandler(Terminal.SignalHandler.SIG_IGN)
-            .dumb(true)
-            .jansi(true)
+            .jansi(SystemUtils.IS_OS_UNIX)
+            .jna(SystemUtils.IS_OS_WINDOWS)
             .build()
 
         // Process 'no-ansi' and 'ansi' commands first (before ASCII title is shown).
diff --git a/nlpcraft/src/main/scala/org/apache/nlpcraft/probe/mgrs/deploy/NCDeployManager.scala b/nlpcraft/src/main/scala/org/apache/nlpcraft/probe/mgrs/deploy/NCDeployManager.scala
index fddc682..eeba3aa 100644
--- a/nlpcraft/src/main/scala/org/apache/nlpcraft/probe/mgrs/deploy/NCDeployManager.scala
+++ b/nlpcraft/src/main/scala/org/apache/nlpcraft/probe/mgrs/deploy/NCDeployManager.scala
@@ -112,6 +112,12 @@
       */
     case class SynonymHolder(elmId: String, syn: NCProbeSynonym)
 
+    /**
+     *
+     * @param method
+     * @param objClassName
+     * @param obj
+     */
     case class MethodOwner(method: Method, objClassName: String, obj: Any) {
         require(method != null)
         require(objClassName != null ^ obj != null)
@@ -120,11 +126,7 @@
 
         def getObject: Any = {
             if (lazyObj == null)
-                try
-                    lazyObj = U.mkObject(objClassName)
-                catch {
-                    case e: Throwable => throw new NCE(s"Error initializing object of type: $objClassName", e)
-                }
+                lazyObj = U.mkObject(objClassName)
 
             lazyObj
         }
@@ -155,6 +157,16 @@
 
         for (makro <- macros.keys if !set.exists(_.contains(makro)))
             logger.warn(s"Unused macro detected [mdlId=${mdl.getId}, macro=$makro]")
+
+        def isSuspicious(s: String): Boolean = //s.toCharArray.toSeq.intersect(SUSP_SYNS_CHARS).nonEmpty
+            SUSP_SYNS_CHARS.exists(susp => s.contains(susp))
+
+        for (makro <- macros)
+            if (isSuspicious(makro._1) || isSuspicious(makro._2))
+                logger.warn(s"Suspicious macro definition (use of ${SUSP_SYNS_CHARS.map(s => s"'$s'").mkString(", ")} chars) [" +
+                    s"mdlId=${mdl.getId}, " +
+                    s"macro=$makro" +
+                s"]")
     }
 
     /**
@@ -231,11 +243,11 @@
             val elmId = elm.getId
 
             // Checks before macros processing.
-            val susp = elm.getSynonyms.asScala.filter(syn => SUSP_SYNS_CHARS.exists(susp => syn.contains(susp)))
+            val susp = elm.getSynonyms.asScala.filter(syn => !syn.contains("//") && SUSP_SYNS_CHARS.exists(susp => syn.contains(susp)))
 
             if (susp.nonEmpty)
                 logger.warn(
-                    s"Suspicious synonyms detected [" +
+                    s"Suspicious synonyms detected (use of ${SUSP_SYNS_CHARS.map(s => s"'$s'").mkString(", ")} chars) [" +
                         s"mdlId=$mdlId, " +
                         s"elementId=$elmId, " +
                         s"synonyms=[${susp.mkString(", ")}]" +
@@ -1721,25 +1733,46 @@
                 if (intAnns.isEmpty && refAnns.isEmpty)
                     throw new NCE(s"@NCIntentSample or @NCIntentSampleRef annotations without corresponding @NCIntent or @NCIntentRef annotations: $mtdStr")
                 else {
-                    def read[T](arr: Array[T], annName: String, getValue: T => Seq[String]): Seq[Seq[String]] = {
-                        val seq = arr.toSeq.map(getValue).map(_.map(_.strip).filter(s => s.nonEmpty && s.head != '#'))
+                    /**
+                     *
+                     * @param annArr
+                     * @param annName
+                     * @param getSamples
+                     * @param getSource
+                     * @tparam T
+                     * @return
+                     */
+                    def read[T](
+                        annArr: Array[T],
+                        annName: String,
+                        getSamples: T => Seq[String],
+                        getSource: Option[T => String]): Seq[Seq[String]] = {
+                            for (ann <- annArr.toSeq) yield {
+                                val samples = getSamples(ann).map(_.strip).filter(s => s.nonEmpty && s.head != '#')
 
-                        if (seq.exists(_.isEmpty))
-                            logger.warn(s"$annName annotation has no samples: $mtdStr")
+                                if (samples.isEmpty) {
+                                    getSource match {
+                                        case None => logger.warn(s"$annName annotation has no samples: $mtdStr")
+                                        case Some(f) => logger.warn(s"$annName annotation references '${f(ann)}' file that has no samples: $mtdStr")
+                                    }
 
-                        seq
-                    }
+                                    Seq.empty
+                                }
+                                else
+                                    samples
+                            }
+                    }.filter(_.nonEmpty)
 
                     val seqSeq =
                         read[NCIntentSample](
-                            smpAnns, "@NCIntentSample", _.value().toSeq
+                            smpAnns, "@NCIntentSample", _.value().toSeq, None
                         ) ++
                         read[NCIntentSampleRef](
-                            smpAnnsRef, "@NCIntentSampleRef", a => U.readAnySource(a.value())
+                            smpAnnsRef, "@NCIntentSampleRef", a => U.readAnySource(a.value()), Some(_.value())
                         )
 
                     if (U.containsDups(seqSeq.flatMap(_.toSeq).toList))
-                        logger.warn(s"@NCIntentSample and @NCIntentSampleRef annotations have duplicates (safely ignoring): $mtdStr")
+                        logger.warn(s"@NCIntentSample and @NCIntentSampleRef annotations have duplicates: $mtdStr")
 
                     val distinct = seqSeq.map(_.distinct).distinct
 
diff --git a/nlpcraft/src/main/scala/org/apache/nlpcraft/probe/mgrs/dialogflow/NCDialogFlowManager.scala b/nlpcraft/src/main/scala/org/apache/nlpcraft/probe/mgrs/dialogflow/NCDialogFlowManager.scala
index b7e667d..c90f918 100644
--- a/nlpcraft/src/main/scala/org/apache/nlpcraft/probe/mgrs/dialogflow/NCDialogFlowManager.scala
+++ b/nlpcraft/src/main/scala/org/apache/nlpcraft/probe/mgrs/dialogflow/NCDialogFlowManager.scala
@@ -177,7 +177,7 @@
             }
 
             val tbl = NCAsciiTable(
-                "",
+                "#",
                 "Intent ID",
                 "Sever Request ID",
                 "Text",
diff --git a/nlpcraft/src/main/scala/org/apache/nlpcraft/probe/mgrs/model/NCModelManager.scala b/nlpcraft/src/main/scala/org/apache/nlpcraft/probe/mgrs/model/NCModelManager.scala
index e0febb3..4f93936 100644
--- a/nlpcraft/src/main/scala/org/apache/nlpcraft/probe/mgrs/model/NCModelManager.scala
+++ b/nlpcraft/src/main/scala/org/apache/nlpcraft/probe/mgrs/model/NCModelManager.scala
@@ -54,6 +54,13 @@
 
             logger.info(s"Models deployed: ${data.size}")
 
+            if (data.isEmpty) {
+                logger.error(s"To start the probe provide $BO${R}at least one model:$RST")
+                logger.error("  +-- Check probe configuration ('probe.conf' file) or -DNLPCRAFT_TEST_MODELS system property if using embedded probe.")
+
+                throw new NCE(s"Probe requires at least one model deployed to start.")
+            }
+
             data.values.foreach(pm => {
                 val mdl = pm.model
 
diff --git a/pom.xml b/pom.xml
index f06819c..3280136 100644
--- a/pom.xml
+++ b/pom.xml
@@ -154,7 +154,7 @@
         <prometheus.ver>0.9.0</prometheus.ver>
         <lightstep.ver>0.0.3</lightstep.ver>
         <lightstep.grpc.ver>0.15.8</lightstep.grpc.ver>
-        <junit.ver>5.5.1</junit.ver>
+        <junit.ver>5.7.2</junit.ver>
         <jsonpath.ver>2.4.0</jsonpath.ver>
 
         <!-- Force specific encoding on text resources. -->
@@ -635,6 +635,7 @@
         <profile>
             <id>examples</id>
             <modules>
+                <module>nlpcraft-examples/cargps</module>
                 <module>nlpcraft-examples/alarm</module>
                 <module>nlpcraft-examples/echo</module>
                 <module>nlpcraft-examples/helloworld</module>