[VOL-5064] - Build and deploy voltha-system-tests

makefiles/
----------
  o Copy in latest library makefiles from repo:onf-make

config.mk
makefiles/lint
--------------
  o Support more lint targets

makefiles/virtualenv.mk
-----------------------
  o Update to use library logic.
  o Install/maintain .venv/ VS vst_venv.
  o Proper dependency driven create when needed VS always install.
  o Also support replacing inlined venv logic with library makefile logs.

makefiles/commands/kail.mk
--------------------------
  o mkdir -p for interactive use when WORKSPACE= is set.

Makefile
--------
  o Inline comment delimiters and help targets to improve readabilty.
  o Call macro banner-enter/banner-leave to hilight target output.
  o Change targets clean and help into double-colon rules so they
    are included when library targets are processed.
  o Update include $(MAKEDIR) imports, library makefiles are able to infer paths
    and define MAKDIR=, ONF_MAKEDIR=.
  o Define helper macro run-robot-test= allowing copy & paste robot command
    line to be refactored and reduced.
  o Define local target 'venv-install' allowing installation of the virtualenv
    followed by patching so a newer interpreter can be used locally for testing.
  o Shell command separator: replace ';' with '&&' to improve error detection.
  o target=gendocs: Split run-on command line into independent steps, activate
    script only applies to the for loop invoking tests.

Change-Id: Idc8efd89f36b9f4954d9394a6524e07aa2ea5531
diff --git a/.gitignore b/.gitignore
index a78008a..d7e76d7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,5 @@
+# -*- makefile -*-
+
 # python virtualenv
 vst_venv
 .venv
@@ -15,3 +17,13 @@
 
 # other outputs
 tests/scale/plots
+
+bin/kail
+
+# Junk in the trunk: *.log
+# ------------------------
+tests/dmi-interface/kafka_robot_*.log
+tests/pm-data/kafka_robot_*.log
+tests/openonu-go-adapter/kafka_robot_*.log
+
+# [EOF]
diff --git a/Jenkinsfile-voltha-test b/Jenkinsfile-voltha-test
index 02ed46a..09df77c 100644
--- a/Jenkinsfile-voltha-test
+++ b/Jenkinsfile-voltha-test
@@ -39,8 +39,8 @@
                     rm -rf *.log
                     export VOLTCONFIG=/home/cord/.volt/config ; sleep 10
                     cd $WORKSPACE/voltha-system-tests
-                    make vst_venv
-                    source vst_venv/bin/activate
+                    make 'venv-install-patched'
+                    source .venv/bin/activate
                     cd tests
                     robot --removekeywords wuks -i sanity -i functional -e bbsim -e notready -d Log -V $WORKSPACE/${configBaseDir}/${configDeploymentDir}/${configFileName}.yaml -v POD_NAME:${configFileName} -v KUBERNETES_CONFIGS_DIR:$WORKSPACE/${configBaseDir}/${configKubernetesDir} functional/Voltha_PODTests.robot || true
                     //robot --removekeywords wuks -i PowerSwitch -i functional -e bbsim -e notready -d Log -T -V $WORKSPACE/${configBaseDir}/${configDeploymentDir}/${configFileName}.yaml -v POD_NAME:${configFileName} -v KUBERNETES_CONFIGS_DIR:$WORKSPACE/${configBaseDir}/${configKubernetesDir} functional/Voltha_FailureScenarios.robot || true                    
diff --git a/Makefile b/Makefile
index 6399c0c..13ff62a 100644
--- a/Makefile
+++ b/Makefile
@@ -17,27 +17,48 @@
 
 .DEFAULT_GOAL := sanity-kind
 
+##-------------------##
+##---]  GLOBALS  [---##
+##-------------------##
+TOP ?=$(strip \
+  $(dir \
+    $(abspath $(lastword $(MAKEFILE_LIST)))\
+   )\
+)
+
 # Assign early: altered by include
 ROOT_DIR  := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))
 
 ##--------------------##
 ##---]  INCLUDES  [---##
 ##--------------------##
-include config.mk
-include makefiles/include.mk
-include makefiles/patches/include.mk
-
-venv-patched    += $(venv-activate-script).patched
+include $(TOP)/config.mk#                # configure
+include $(TOP)/makefiles/include.mk      # top level include
 
 # Configuration and lists of files for linting/testing
 VERSION   ?= $(shell cat ./VERSION)
 
-PYTHON_FILES := $(wildcard libraries/*.py)
-ROBOT_FILES  := $(shell find . -name *.robot -print)
-YAML_FILES   := $(shell find ./tests -type f \( -name *.yaml -o -name *.yml \) -print)
-JSON_FILES   := $(shell find ./tests -name *.json -print)
+## -----------------------------------------------------------------------
+## Consumed by makefiles/lint/*/include.mk
+## -----------------------------------------------------------------------
+# JSON_FILES   := $(shell find ./tests -name *.json -print)
+# PYTHON_FILES := $(wildcard libraries/*.py)
+# ROBOT_FILES  := $(shell find . -name *.robot -print)
+# YAML_FILES   := $(shell find ./tests -type f \( -name *.yaml -o -name *.yml \) -print)
 
+## -----------------------------------------------------------------------
+## Intent: Helper macros
+## -----------------------------------------------------------------------
+run-robot-test =$(strip \
+  $(foreach path,$(1),\
+    $(activate) \
+      && cd $(path) \
+      && robot -V $(ROBOT_CONFIG_FILE) $(ROBOT_MISC_ARGS) $(ROBOT_FILE) \
+  ))
+
+## -----------------------------------------------------------------------
 # Robot config
+## -----------------------------------------------------------------------
 ROBOT_SANITY_SINGLE_PON_FILE    ?= $(ROOT_DIR)/tests/data/bbsim-kind.yaml
 ROBOT_SANITY_DT_SINGLE_PON_FILE    ?= $(ROOT_DIR)/tests/data/bbsim-kind-dt.yaml
 ROBOT_SANITY_DT_SINGLE_PON_FILE_VGC    ?= $(ROOT_DIR)/tests/data/bbsim-kind-dt-vgc.yaml
@@ -81,7 +102,15 @@
 # to simplify ci
 sanity-kind-att: sanity-single-kind
 
+# -----------------------------------------------------------------------
+# -----------------------------------------------------------------------
+help ::
+	@echo '  sanity-kind-multiuni-att'
+	@echo '  functional-single-kind-multiuni-att'
+
+# -----------------------------------------------------------------------
 # ATT Multi-UNI Sanity Target
+# -----------------------------------------------------------------------
 sanity-kind-multiuni-att: ROBOT_MISC_ARGS += -X -i sanity $(ROBOT_DEBUG_LOG_OPT)
 sanity-kind-multiuni-att: ROBOT_CONFIG_FILE := $(ROBOT_SANITY_MULTI_UNI_SINGLE_PON_FILE)
 sanity-kind-multiuni-att: ROBOT_FILE := Voltha_PODTests.robot
@@ -93,7 +122,15 @@
 functional-single-kind-multiuni-att: ROBOT_FILE := Voltha_PODTests.robot
 functional-single-kind-multiuni-att: voltha-test
 
+# -----------------------------------------------------------------------
+# -----------------------------------------------------------------------
+help ::
+	@echo '  voltha-scale'
+	@echo '  voltha-scale-onu-upgrade'
+
+# -----------------------------------------------------------------------
 # for scale pipeline
+# -----------------------------------------------------------------------
 voltha-scale: ROBOT_MISC_ARGS += -i activation -v NAMESPACE:voltha $(ROBOT_DEBUG_LOG_OPT)
 voltha-scale: voltha-scale-test
 
@@ -103,30 +140,56 @@
 voltha-scale-onu-upgrade: ROBOT_MISC_ARGS += -i setup -i activation -i onu-upgrade -v NAMESPACE:voltha -v image_version:BBSM_IMG_00002 -v image_url:http://bbsim0:50074/images/software-image.img -v image_vendor:BBSM -v image_activate_on_success:false -v image_commit_on_success:false -v image_crc:0 $(ROBOT_DEBUG_LOG_OPT)
 voltha-scale-onu-upgrade: voltha-scale-test
 
+# -----------------------------------------------------------------------
+# -----------------------------------------------------------------------
+help ::
+	@echo '  sanity-kind-dt'
+	@echo '  sanity-kind-dt-vgc'
+	@echo '  sanity-kind-dt-fttb'
+	@echo '  sanity-kind-dt-fttb-vgc'
+
+# -----------------------------------------------------------------------
 # target to invoke DT Workflow Sanity
+# -----------------------------------------------------------------------
 sanity-kind-dt: ROBOT_MISC_ARGS += -i sanityDt $(ROBOT_DEBUG_LOG_OPT)
 sanity-kind-dt: ROBOT_CONFIG_FILE := $(ROBOT_SANITY_DT_SINGLE_PON_FILE)
 sanity-kind-dt: ROBOT_FILE := Voltha_DT_PODTests.robot
 sanity-kind-dt: voltha-dt-test
 
+# -----------------------------------------------------------------------
 # target to invoke DT Workflow Sanity for VGC
+# -----------------------------------------------------------------------
 sanity-kind-dt-vgc: ROBOT_MISC_ARGS += -i sanityDt $(ROBOT_DEBUG_LOG_OPT)
 sanity-kind-dt-vgc: ROBOT_CONFIG_FILE := $(ROBOT_SANITY_DT_SINGLE_PON_FILE_VGC)
 sanity-kind-dt-vgc: ROBOT_FILE := Voltha_DT_PODTests_VGC.robot
 sanity-kind-dt-vgc: voltha-dt-test
 
+# -----------------------------------------------------------------------
 # target to invoke DT FTTB Workflow Sanity
+# -----------------------------------------------------------------------
 sanity-kind-dt-fttb: ROBOT_MISC_ARGS += -i sanityDtFttb $(ROBOT_DEBUG_LOG_OPT)
 sanity-kind-dt-fttb: ROBOT_CONFIG_FILE := $(ROBOT_SANITY_DT_FTTB_SINGLE_PON_FILE)
 sanity-kind-dt-fttb: ROBOT_FILE := Voltha_DT_FTTB_Tests.robot
 sanity-kind-dt-fttb: voltha-dt-test
 
+# -----------------------------------------------------------------------
 # target to invoke DT FTTB Workflow Sanity for VGC
+# -----------------------------------------------------------------------
 sanity-kind-dt-fttb-vgc: ROBOT_MISC_ARGS += -i sanityDtFttb $(ROBOT_DEBUG_LOG_OPT)
 sanity-kind-dt-fttb-vgc: ROBOT_CONFIG_FILE := $(ROBOT_SANITY_DT_FTTB_SINGLE_PON_FILE_VGC)
 sanity-kind-dt-fttb-vgc: ROBOT_FILE := Voltha_DT_FTTB_Tests_VGC.robot
 sanity-kind-dt-fttb-vgc: voltha-dt-test
 
+# -----------------------------------------------------------------------
+# -----------------------------------------------------------------------
+help ::
+	@echo '  functional-single-kind'
+	@echo '  functional-single-kind-att'
+	@echo '  functional-single-kind-dt'
+	@echo '  functional-single-kind-dt-vgc'
+
+# -----------------------------------------------------------------------
+# -----------------------------------------------------------------------
 functional-single-kind: ROBOT_MISC_ARGS += -i sanityORfunctional -e PowerSwitch $(ROBOT_DEBUG_LOG_OPT)
 functional-single-kind: ROBOT_CONFIG_FILE := $(ROBOT_SANITY_SINGLE_PON_FILE)
 functional-single-kind: bbsim-kind
@@ -134,78 +197,132 @@
 # to simplify ci
 functional-single-kind-att: functional-single-kind
 
+# -----------------------------------------------------------------------
 # target to invoke DT Workflow Functional scenarios
+# -----------------------------------------------------------------------
 functional-single-kind-dt: ROBOT_MISC_ARGS += -i sanityDtORfunctionalDt -e PowerSwitch $(ROBOT_DEBUG_LOG_OPT)
 functional-single-kind-dt: ROBOT_CONFIG_FILE := $(ROBOT_SANITY_DT_SINGLE_PON_FILE)
 functional-single-kind-dt: ROBOT_FILE := Voltha_DT_PODTests.robot
 functional-single-kind-dt: voltha-dt-test
 
+# -----------------------------------------------------------------------
 # target to invoke DT Workflow Functional scenarios
+# -----------------------------------------------------------------------
 functional-single-kind-dt-vgc: ROBOT_MISC_ARGS += -i sanityDtORfunctionalDt -e PowerSwitch $(ROBOT_DEBUG_LOG_OPT)
 functional-single-kind-dt-vgc: ROBOT_CONFIG_FILE := $(ROBOT_SANITY_DT_SINGLE_PON_FILE_VGC)
 functional-single-kind-dt-vgc: ROBOT_FILE := Voltha_DT_PODTests_VGC.robot
 functional-single-kind-dt-vgc: voltha-dt-test
 
+# -----------------------------------------------------------------------
+# -----------------------------------------------------------------------
+help ::
+	@echo '  sanity-kind-tt'
+	@echo '  sanity-kind-tt-maclearning'
+	@echo '  sanity-kind-multiuni-tt'
 
+# -----------------------------------------------------------------------
 # target to invoke TT Workflow Sanity
+# -----------------------------------------------------------------------
 sanity-kind-tt: ROBOT_MISC_ARGS += -i sanityTT $(ROBOT_DEBUG_LOG_OPT)
 sanity-kind-tt: ROBOT_CONFIG_FILE := $(ROBOT_SANITY_TT_SINGLE_PON_FILE)
 sanity-kind-tt: ROBOT_FILE := Voltha_TT_PODTests.robot
 sanity-kind-tt: voltha-tt-test
 
+# -----------------------------------------------------------------------
+# -----------------------------------------------------------------------
 sanity-kind-tt-maclearning: ROBOT_MISC_ARGS += -i sanityTT -v with_maclearning:True $(ROBOT_DEBUG_LOG_OPT)
 sanity-kind-tt-maclearning: ROBOT_CONFIG_FILE := $(ROBOT_SANITY_TT_SINGLE_PON_FILE)
 sanity-kind-tt-maclearning: ROBOT_FILE := Voltha_TT_PODTests.robot
 sanity-kind-tt-maclearning: voltha-tt-test
 
+# -----------------------------------------------------------------------
+# -----------------------------------------------------------------------
 sanity-kind-multiuni-tt: ROBOT_MISC_ARGS += -i sanityTT $(ROBOT_DEBUG_LOG_OPT)
 sanity-kind-multiuni-tt: ROBOT_CONFIG_FILE := $(ROBOT_SANITY_TT_MULTI_UNI_SINGLE_PON_FILE)
 sanity-kind-multiuni-tt: ROBOT_FILE := Voltha_TT_PODTests.robot
 sanity-kind-multiuni-tt: voltha-tt-test
 
+# -----------------------------------------------------------------------
+# -----------------------------------------------------------------------
+help ::
+	@echo '  functional-single-kind-tt'
+	@echo '  functional-single-kind-multiuni-tt'
+
+# -----------------------------------------------------------------------
 # target to invoke TT Workflow Functional scenarios
+# -----------------------------------------------------------------------
 functional-single-kind-tt: ROBOT_MISC_ARGS += -i sanityTTORfunctionalTT -e PowerSwitch $(ROBOT_DEBUG_LOG_OPT)
 functional-single-kind-tt: ROBOT_CONFIG_FILE := $(ROBOT_SANITY_TT_SINGLE_PON_FILE)
 functional-single-kind-tt: ROBOT_FILE := Voltha_TT_PODTests.robot
 functional-single-kind-tt: voltha-tt-test
 
+# -----------------------------------------------------------------------
+# -----------------------------------------------------------------------
 functional-single-kind-multiuni-tt: ROBOT_MISC_ARGS += -i sanityTTORfunctionalTT -e PowerSwitch $(ROBOT_DEBUG_LOG_OPT)
 functional-single-kind-multiuni-tt: ROBOT_CONFIG_FILE := $(ROBOT_SANITY_TT_MULTI_UNI_SINGLE_PON_FILE)
 functional-single-kind-multiuni-tt: ROBOT_FILE := Voltha_TT_PODTests.robot
 functional-single-kind-multiuni-tt: voltha-tt-test
 
+# -----------------------------------------------------------------------
+# -----------------------------------------------------------------------
+help ::
+	@echo '  sanity-kind-tim'
+	@echo '  sanity-kind-tim-multi-onu'
+	@echo '  sanity-kind-tim-multi-pon-multi-onu'
+	@echo '  sanity-kind-tim-multi-olt-multi-pon-multi-onu'
+
+# -----------------------------------------------------------------------
 # target to invoke TIM Workflow Sanity
+# -----------------------------------------------------------------------
 sanity-kind-tim: ROBOT_MISC_ARGS += -i sanityTIM $(ROBOT_DEBUG_LOG_OPT)
 sanity-kind-tim: ROBOT_CONFIG_FILE := $(ROBOT_SANITY_TIM_SINGLE_PON_FILE)
 sanity-kind-tim: ROBOT_FILE := Voltha_TIM_PODTests.robot
 sanity-kind-tim: voltha-tim-test
 
+# -----------------------------------------------------------------------
+# -----------------------------------------------------------------------
 sanity-kind-tim-multi-onu: ROBOT_MISC_ARGS += -i sanityTIM $(ROBOT_DEBUG_LOG_OPT)
 sanity-kind-tim-multi-onu: ROBOT_CONFIG_FILE := $(ROBOT_SANITY_TIM_SINGLE_PON_MULTI_ONU_FILE)
 sanity-kind-tim-multi-onu: ROBOT_FILE := Voltha_TIM_PODTests.robot
 sanity-kind-tim-multi-onu: voltha-tim-test
 
+# -----------------------------------------------------------------------
+# -----------------------------------------------------------------------:
 sanity-kind-tim-multi-pon-multi-onu: ROBOT_MISC_ARGS += -i sanityTIM $(ROBOT_DEBUG_LOG_OPT)
 sanity-kind-tim-multi-pon-multi-onu: ROBOT_CONFIG_FILE := $(ROBOT_SANITY_TIM_MULTI_PON_MULTI_ONU_FILE)
 sanity-kind-tim-multi-pon-multi-onu: ROBOT_FILE := Voltha_TIM_PODTests.robot
 sanity-kind-tim-multi-pon-multi-onu: voltha-tim-test
 
+# -----------------------------------------------------------------------
+# -----------------------------------------------------------------------:
 sanity-kind-tim-multi-olt-multi-pon-multi-onu: ROBOT_MISC_ARGS += -i sanityTIM $(ROBOT_DEBUG_LOG_OPT)
 sanity-kind-tim-multi-olt-multi-pon-multi-onu: ROBOT_CONFIG_FILE := $(ROBOT_SANITY_TIM_MULTI_OLT_MULTI_PON_MULTI_ONU_FILE)
 sanity-kind-tim-multi-olt-multi-pon-multi-onu: ROBOT_FILE := Voltha_TIM_PODTests.robot
 sanity-kind-tim-multi-olt-multi-pon-multi-onu: voltha-tim-test
 
+# -----------------------------------------------------------------------
+# -----------------------------------------------------------------------
+help ::
+	@echo '  sanity-kind-tim-mcast'
+	@echo '  sanity-kind-tim-mcast-multi-olt-multi-pon-multi-onu'
+
+# -----------------------------------------------------------------------
+# -----------------------------------------------------------------------
 sanity-kind-tim-mcast: ROBOT_MISC_ARGS += -i sanityTIM-MCast $(ROBOT_DEBUG_LOG_OPT)
 sanity-kind-tim-mcast: ROBOT_CONFIG_FILE := $(ROBOT_SANITY_TIM_MCAST_SINGLE_PON_FILE)
 sanity-kind-tim-mcast: ROBOT_FILE := Voltha_TIM_PODTests.robot
 sanity-kind-tim-mcast: voltha-tim-test
 
+# -----------------------------------------------------------------------
+# -----------------------------------------------------------------------
 sanity-kind-tim-mcast-multi-olt-multi-pon-multi-onu: ROBOT_MISC_ARGS += -i sanityTIM-MCast $(ROBOT_DEBUG_LOG_OPT)
 sanity-kind-tim-mcast-multi-olt-multi-pon-multi-onu: ROBOT_CONFIG_FILE := $(ROBOT_SANITY_TIM_MCAST_MULTI_OLT_MULTI_PON_MULTI_ONU_FILE)
 sanity-kind-tim-mcast-multi-olt-multi-pon-multi-onu: ROBOT_FILE := Voltha_TIM_PODTests.robot
 sanity-kind-tim-mcast-multi-olt-multi-pon-multi-onu: voltha-tim-test
 
+# -----------------------------------------------------------------------
 # target to invoke multiple OLTs Functional scenarios
+# -----------------------------------------------------------------------
 functional-multi-olt: ROBOT_MISC_ARGS += -i sanityORfunctional -e PowerSwitch $(ROBOT_DEBUG_LOG_OPT)
 functional-multi-olt: ROBOT_CONFIG_FILE := $(ROBOT_SANITY_MULTIPLE_OLT_FILE)
 functional-multi-olt: ROBOT_FILE := Voltha_PODTests.robot
@@ -349,28 +466,52 @@
 sanity-single-kind: ROBOT_CONFIG_FILE := $(ROBOT_SANITY_SINGLE_PON_FILE)
 sanity-single-kind: bbsim-kind
 
+## -----------------------------------------------------------------------
+## Intent: sanity-bbsim tests
+## -----------------------------------------------------------------------
+help ::
+	@echo '  sanity-bbsim{-att,-dt,-tt}'
+	@echo '  voltha-bbsim-test        Parameterized test target'
+
+## -----------------------------------------------------------------------
+## -----------------------------------------------------------------------
 sanity-bbsim-att: ROBOT_MISC_ARGS += -v workflow:ATT
 sanity-bbsim-att: sanity-bbsim
 
+## -----------------------------------------------------------------------
+## -----------------------------------------------------------------------
 sanity-bbsim-dt: ROBOT_MISC_ARGS += -v workflow:DT
 sanity-bbsim-dt: ROBOT_CONFIG_FILE := $(ROBOT_SANITY_DT_SINGLE_PON_FILE)
 sanity-bbsim-dt: ROBOT_FILE := Voltha_BBSimTests.robot
 sanity-bbsim-dt: voltha-bbsim-test
 
+## -----------------------------------------------------------------------
+## -----------------------------------------------------------------------
 sanity-bbsim-tt: ROBOT_MISC_ARGS += -v workflow:TT
 sanity-bbsim-tt: ROBOT_CONFIG_FILE := $(ROBOT_SANITY_TT_SINGLE_PON_FILE)
 sanity-bbsim-tt: ROBOT_FILE := Voltha_BBSimTests.robot
 sanity-bbsim-tt: voltha-bbsim-test
 
+## -----------------------------------------------------------------------
+## -----------------------------------------------------------------------
 sanity-bbsim: ROBOT_MISC_ARGS += -i bbsimSanity $(ROBOT_DEBUG_LOG_OPT)
 sanity-bbsim: ROBOT_CONFIG_FILE := $(ROBOT_SANITY_SINGLE_PON_FILE)
 sanity-bbsim: ROBOT_FILE := Voltha_BBSimTests.robot
 sanity-bbsim: voltha-bbsim-test
 
-voltha-bbsim-test: $(venv-activate-patched)
-	$(activate) \
-	  && cd tests/bbsim \
-	  && robot -V $(ROBOT_CONFIG_FILE) $(ROBOT_MISC_ARGS) $(ROBOT_FILE)
+## -----------------------------------------------------------------------
+## Intent:
+##   o $(MAKE) Named targets provides macro definitions.
+##   o Alias uninitialized vars to improve readability
+## -----------------------------------------------------------------------
+# ROBOT_CONFIG_FILE ?= $(error ROBOT_CONFIG_FILE= is required)
+# ROBOT_FILE        ?= $(error ROBOT_FILE= is required)
+
+## -----------------------------------------------------------------------
+## Intent: Parameterized test target
+## -----------------------------------------------------------------------
+voltha-bbsim-test: venv-activate-patched
+	$(call run-robot-test,tests/bbsim)
 
 rwcore-restart-single-kind: ROBOT_MISC_ARGS += -X -i functionalANDrwcore-restart $(ROBOT_DEBUG_LOG_OPT)
 rwcore-restart-single-kind: ROBOT_CONFIG_FILE := $(ROBOT_FAIL_SINGLE_PON_FILE)
@@ -509,10 +650,10 @@
 
 voltha-test: ROBOT_MISC_ARGS += -e notready --noncritical non-critical
 
-voltha-test: $(venv-activate-patched)
-	$(activate) \
-	  && cd tests/functional \
-	  && robot -V $(ROBOT_CONFIG_FILE) $(ROBOT_MISC_ARGS) $(ROBOT_FILE)
+## -----------------------------------------------------------------------
+## -----------------------------------------------------------------------
+voltha-test: venv-activate-patched
+	$(call run-robot-test,tests/functional)
 
 bbsim-dmi-hw-management-test: ROBOT_MISC_ARGS +=  -e notreadyDMI -i functionalDMI -e bbsimUnimplementedDMI
 bbsim-dmi-hw-management-test: ROBOT_FILE := dmi-hw-management.robot
@@ -524,10 +665,10 @@
 voltha-dmi-hw-management-test: ROBOT_CONFIG_FILE := $(ROBOT_DMI_SINGLE_ADTRAN_FILE)
 voltha-dmi-hw-management-test: voltha-dmi-test
 
-voltha-dmi-test: $(venv-activate-patched)
-	$(activate) \
-	  && tests/dmi-interface \
-	  && robot -V $(ROBOT_CONFIG_FILE) $(ROBOT_MISC_ARGS) $(ROBOT_FILE)
+## -----------------------------------------------------------------------
+## -----------------------------------------------------------------------
+voltha-dmi-test: venv-activate-patched
+	$(call run-robot-test,tests/dmi-interface)
 
 # target to invoke single ONU pm data scenarios in ATT workflow
 voltha-pm-data-single-kind-att: ROBOT_MISC_ARGS += -v workflow:ATT
@@ -564,9 +705,14 @@
 voltha-pm-data-tests: ROBOT_FILE := Voltha_ONUPMTests.robot
 voltha-pm-data-tests: voltha-pm-data-test
 
-voltha-pm-data-test: $(venv-activate-patched)
+## -----------------------------------------------------------------------
+## -----------------------------------------------------------------------
+voltha-pm-data-test: venv-activate-patched
+# ROBOT_PM_CONFIG_FILE= is differnet
+#	$(call run-robot-test,tests/pm-data)
+
 	$(activate) \
-	  && tests/pm-data \
+	  && cd tests/pm-data \
 	  && robot -V $(ROBOT_CONFIG_FILE) -V $(ROBOT_PM_CONFIG_FILE) $(ROBOT_MISC_ARGS) $(ROBOT_FILE)
 
 # target to invoke single ONU OMCI Get scenarios in ATT workflow
@@ -735,117 +881,108 @@
 voltha-onu-robustness-tests: ROBOT_FILE := Voltha_ONUErrorTests.robot
 voltha-onu-robustness-tests: openonu-go-adapter-tests
 
-software-upgrade-test: $(venv-activate-patched)
+software-upgrade-test: venv-activate-patched
 	$(activate) \
 	  && cd tests/software-upgrades \
 	  && robot -V $(ROBOT_CONFIG_FILE) $(ROBOT_MISC_ARGS) $(ROBOT_FILE)
 
 voltha-dt-test: ROBOT_MISC_ARGS += -e notready  --noncritical non-critical
 
-voltha-dt-test: $(venv-activate-patched)
+## CHECK
+voltha-dt-test: venv-activate-patched
 	$(activate) \
 	  && cd tests/dt-workflow \
 	  && robot -V $(ROBOT_CONFIG_FILE) $(ROBOT_MISC_ARGS) $(ROBOT_FILE)
 
 voltha-tt-test: ROBOT_MISC_ARGS += -e notready  --noncritical non-critical
 
-voltha-tt-test: $(venv-activate-patched)
+## CHECK
+voltha-tt-test: venv-activate-patched
 	$(activate) \
 	  && cd tests/tt-workflow \
 	  && robot -V $(ROBOT_CONFIG_FILE) $(ROBOT_MISC_ARGS) $(ROBOT_FILE)
 
 voltha-tim-test: ROBOT_MISC_ARGS += -e notready  --noncritical non-critical
 
-voltha-tim-test: $(venv-activate-patched)
+## Check
+voltha-tim-test: venv-activate-patched
 	$(activate) \
 	  && cd tests/tim-workflow \
 	  && robot -V $(ROBOT_CONFIG_FILE) $(ROBOT_MISC_ARGS) $(ROBOT_FILE)
 
-voltha-scale-test: $(venv-activate-patched)
+## CHECK
+voltha-scale-test: venv-activate-patched
 	$(activate) \
 	  && cd tests/scale \
 	  && robot $(ROBOT_MISC_ARGS) Voltha_Scale_Tests.robot
 
-openonu-go-adapter-tests: $(venv-activate-patched)
+## CHECK
+openonu-go-adapter-tests: venv-activate-patched
 	$(activate) \
 	  && cd tests/openonu-go-adapter \
 	  && robot -V $(ROBOT_CONFIG_FILE) $(ROBOT_MISC_ARGS) $(ROBOT_FILE)
 
 voltha-bbf-adapter-test: ROBOT_MISC_ARGS += -e notready  --noncritical non-critical
-voltha-bbf-adapter-test: $(venv-activate-patched)
-	$(activate) \
-	  && cd tests/bbf-adapter \
-	  && robot -V $(ROBOT_CONFIG_FILE) $(ROBOT_MISC_ARGS) $(ROBOT_FILE)
+voltha-bbf-adapter-test: venv-activate-patched
+	$(call run-robot-test,tests/bbf-adapter)
 
-voltha-memory-leak-test :$(venv-activate-patched)
-	$(activate) \
-	  && cd tests/memory-leak \
-	  && robot -V $(ROBOT_CONFIG_FILE) $(ROBOT_MISC_ARGS) $(ROBOT_FILE)
-
-## -----------------------------------------------------------------------
-## -----------------------------------------------------------------------
-help ::
-	@echo '  voltha-memory-leak-test      Test suite'
-
-# self-test, lint, and setup targets
-
-# -----------------------------------------------------------------------
-# virtualenv for the robot tools
-# VOL-2724 Invoke pip via python3 to avoid pathname too long on QA jobs
-# Verify installation: make lint -or- make test
-# vol-4874 - python_310_migration.sh
-# -----------------------------------------------------------------------
-vst_venv          : $(venv-activate-patched)#    # verify not needed then remove
+voltha-memory-leak-test: venv-activate-patched
+	$(call run-robot-test,tests/memory-leak)
 
 ##----------------##
 ##---]  TEST  [---##
 ##----------------##
 test: lint
 
+# -----------------------------------------------------------------------
 # tidy target will be more useful once issue with removing leading comments
 # is resolved: https://github.com/robotframework/robotframework/issues/3263
-tidy-robot: $(venv-activate-patched)
-	$(activate) \
-	  && python -m robot.tidy --inplace $(ROBOT_FILES);
+# -----------------------------------------------------------------------
+tidy-robot: venv-activate-patched
+	$(activate) && python -m robot.tidy --inplace $(ROBOT_FILES)
 
 ## Variables for gendocs
-TEST_SOURCE := $(wildcard tests/*/*.robot)
+TEST_SOURCE   := $(wildcard tests/*/*.robot)
 TEST_BASENAME := $(basename $(TEST_SOURCE))
-TEST_DIRS := $(dir $(TEST_SOURCE))
+TEST_DIRS     := $(dir $(TEST_SOURCE))
 
 LIB_SOURCE   := $(wildcard libraries/*.robot)
 LIB_BASENAME := $(basename $(LIB_SOURCE))
 LIB_DIRS     := $(sort $(dir $(LIB_SOURCE)))
 
-## -----------------------------------------------------------------------
-## -----------------------------------------------------------------------
+# -----------------------------------------------------------------------
+# -----------------------------------------------------------------------
+help ::
+	@echo '  gendocs'
+	@echo '  tidy-robot'
+
+# -----------------------------------------------------------------------
+# -----------------------------------------------------------------------
 .PHONY: gendocs lint test
 # In future explore use of --docformat REST - integration w/Sphinx?
-gendocs: $(venv-activate-patched)
+gendocs: venv-activate-patched
 
-	$(HIDE)echo " ** $(make) $@: ENTER"
+	$(call banner-enter)
+
+	@echo
+	@echo " ** $(MAKE) $@: robot.libdoc"
+	@mkdir -pv $(addprefix $@/,$(LIB_DIRS))
 
 	$(activate) \
-	  && set -u \
-	  && echo \
-	  && echo " ** $(make) $@: robot.libdoc" \
-	  && mkdir -pv $(addprefix $@/,$(LIB_DIRS)) \
 	  && for dir in $(LIB_BASENAME); do\
-	      python -m robot.libdoc --format HTML $$dir.robot $@/$$dir.html ;\
-	  done \
-	  && echo \
-	  && echo " ** $(make) $@: robot.testdoc" \
-	  && mkdir -vp $(addprefix $@/,$(TEST_DIRS)) \
+	    python -m robot.libdoc --format HTML $$dir.robot $@/$$dir.html ;\
+	  done
+
+	@echo
+	@echo " ** $(make) $@: robot.testdoc"
+	@mkdir -vp $(addprefix $@/,$(TEST_DIRS))
+
+	$(activate) \
 	  && for dir in $(TEST_BASENAME); do\
 		python -m robot.testdoc $$dir.robot $@/$$dir.html ;\
 	  done
 
-	$(HIDE)echo " ** $(make) $@: LEAVE"
-
-## -----------------------------------------------------------------------
-## -----------------------------------------------------------------------
-help ::
-	@echo '  gendocs                Generate robot test framework documentation'
+	$(call banner-leave)
 
 ## -----------------------------------------------------------------------
 ## -----------------------------------------------------------------------
@@ -855,8 +992,20 @@
 
 ## -----------------------------------------------------------------------
 ## -----------------------------------------------------------------------
+clean-all sterile :: clean
+	$(RM) -r venv-activate-patched
+
+# -----------------------------------------------------------------------
+# -----------------------------------------------------------------------
+help ::
+	@echo '  voltctl-docker-image-build'
+	@echo '  voltctl-docker-image-install-kind'
+
+## -----------------------------------------------------------------------
+## -----------------------------------------------------------------------
 voltctl-docker-image-build:
-	cd docker && docker build -t opencord/voltctl:local -f Dockerfile.voltctl .
+	cd docker \
+	  && docker build -t opencord/voltctl:local -f Dockerfile.voltctl .
 
 ## -----------------------------------------------------------------------
 ## -----------------------------------------------------------------------
@@ -865,7 +1014,6 @@
 	kind load docker-image --name `kind get clusters | grep kind` opencord/voltctl:local
 
 ## -----------------------------------------------------------------------
-## Intent: [yuck] replace with a standalone reusable installer 4script
 ## -----------------------------------------------------------------------
 .PHONY: voltctl-download-url
 voltctl-download-url:
@@ -873,6 +1021,4 @@
 	    | grep 'browser_download_url' \
 	    | grep 'linux-amd64'
 
-# [latest] https://github.com/opencord/voltctl/releases/download/untagged-cd611c39178f25b95a87/voltctl-1.9.1-linux-amd64
-
 # [EOF]
diff --git a/config.mk b/config.mk
index d9acade..043fa08 100644
--- a/config.mk
+++ b/config.mk
@@ -16,30 +16,30 @@
 # -----------------------------------------------------------------------
 # https://gerrit.opencord.org/plugins/gitiles/onf-make
 # ONF.makefiles.include.version = 1.1
-# ONF.confg.mk                  = 1.5
+# ONF.confg.mk                  = 1.6
 # -----------------------------------------------------------------------
 
---repo-name-- := votlha-system-tests
+--repo-name-- := voltha-system-tests
 --repo-name-- ?= $(error --repo-name--= is required)
 
 ##--------------------------------##
 ##---]  Disable lint targets  [---##
 ##--------------------------------##
-# NO-LINT-DOC8      := true
-# NO-LINT-GOLANG    := true
-NO-LINT-GROOVY      := true#               # Note[2]
-NO-LINT-JJB         := true#               # Note[2]
-# NO-LINT-JSON      := true#               # Note[1]
-NO-LINT-MAKEFILE    := true#               # Note[1]
-NO-LINT-REUSE       := true                # License check
-# NO-LINT-ROBOT     := true
-NO-LINT-SHELLCHECK  := true#               # Note[1]
-NO-LINT-TOX         := true#               # Note[1]
-# NO-LINT-YAML      := true#               # Note[1]
+# NO-LINT-DOC8        := true
+# NO-LINT-GOLANG      := true
+NO-LINT-GROOVY        := true#               # Note[1]
+NO-LINT-JJB           := true#               # Note[2]
+# NO-LINT-JSON        := true#               # Note[1]
+NO-LINT-MAKEFILE      := true#               # Note[1]
+NO-LINT-REUSE         := true                # License check
+# NO-LINT-ROBOT       := true
+NO-LINT-SHELLCHECK    := true#               # Note[1]
+NO-LINT-TOX           := true#               # Note[1]
+# NO-LINT-YAML        := true#               # Note[1]
 
-# NO-LINT-FLAKE8    := true#               # Note[1]
-NO-LINT-PYTHON      := true#               # Note[1]
-# NO-LINT-PYLINT    := true#               # Note[1]
+# NO-LINT-FLAKE8      := true#               # Note[1]
+NO-LINT-PYTHON        := true#               # Note[1]
+# NO-LINT-PYLINT      := true#               # Note[1]
 
 # Note[1] - A boatload of source to cleanup prior to enable.
 # Note[2] - No sources available
diff --git a/makefiles/commands/kail.mk b/makefiles/commands/kail.mk
index 33109dd..45232cc 100644
--- a/makefiles/commands/kail.mk
+++ b/makefiles/commands/kail.mk
@@ -23,6 +23,7 @@
 	@echo "  kail            Install the kail command"
 ifdef VERBOSE
 	@echo "                  make kail KAIL_PATH="
+	@echo "    export WORKSPACE=$(/bin/pwd) # i_am=jenkins"
 endif
 
 # -----------------------------------------------------------------------
diff --git a/makefiles/git/ci-management.mk b/makefiles/git/ci-management.mk
new file mode 100644
index 0000000..373dc23
--- /dev/null
+++ b/makefiles/git/ci-management.mk
@@ -0,0 +1,80 @@
+# -*- makefile -*-
+# -----------------------------------------------------------------------
+# Copyright 2022-2023 Open Networking Foundation (ONF) and the ONF Contributors
+#
+# Licensed 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.
+#
+# SPDX-FileCopyrightText: 2022 Open Networking Foundation (ONF) and the ONF Contributors
+# SPDX-License-Identifier: Apache-2.0
+# -----------------------------------------------------------------------
+
+$(if $(DEBUG),$(warning ENTER))
+
+GIT ?= git
+
+## -----------------------------------------------------------------------
+## Intent: Checkout submodules required by ci-management
+## -----------------------------------------------------------------------
+submodule-repos := $(null)
+submodule-repos += global-jjb
+submodule-repos += lf-ansible
+submodule-repos += packer
+
+submodule-deps := $(null)
+submodule-deps += submodules#     # named pseudo target
+submodule-deps += $(submodule-repos)
+
+.PHONY: $(submodule-deps)
+$(submodule-deps):
+	@echo
+	@echo "Checkout dependent submodules"
+	$(GIT) submodule init
+	$(GIT) submodule update
+
+# Abstraction: named target for submodule checkout
+checkout-ci-management-sub-modules: $(submodule-repos)
+
+## -----------------------------------------------------------------------
+## Intent: Revert sandbox to a pristine state.
+## -----------------------------------------------------------------------
+sterile ::
+	$(RM) -r $(submodule-repos)
+
+        # FIXME:
+        #   o restore hierarchy to avoid git status 'deleted:'
+        #   o remove: externals should not be under revision control
+	$(GIT) co $(submodule-repos)
+
+## -----------------------------------------------------------------------
+## -----------------------------------------------------------------------
+help ::
+	@echo
+	@echo '[GIT-SUBMODULES: docs]'
+	@echo '  reload              Setup to auto-reload sphinx doc changes in browser'
+	@echo
+	@echo '[GIT-SUBMODULES: deps]'
+	@echo '  submodules          Checkout dependent git submodules'
+  ifdef VERBOSE
+	@echo '  global-jjb          Checkout ci-management submodule global-jjb'
+	@echo '  lf-ansible          Checkout ci-management submodule lf-ansible'
+	@echo '  packer              Checkout ci-management submodule packer'
+  endif
+
+## -----------------------------------------------------------------------
+## -----------------------------------------------------------------------
+todo ::
+	@echo "Generalize logc, update to depend on .git/ rather than named targets."
+
+$(if $(DEBUG),$(warning LEAVE))
+
+# [EOF]
diff --git a/makefiles/git/help.mk b/makefiles/git/help.mk
new file mode 100644
index 0000000..cbd33ee
--- /dev/null
+++ b/makefiles/git/help.mk
@@ -0,0 +1,31 @@
+# -*- makefile -*-
+# -----------------------------------------------------------------------
+# Copyright 2022-2023 Open Networking Foundation (ONF) and the ONF Contributors
+#
+# Licensed 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.
+# -----------------------------------------------------------------------
+# Intent: Helper makefile target used to setup for a release
+# -----------------------------------------------------------------------
+
+## ---------------------------------------------------------------------------
+## Intent: Display supported targets
+## ---------------------------------------------------------------------------
+help-onf-git :
+	@echo
+	@echo '[GIT]'
+	@echo '  show-submodules     Display a list of repository submodules and versions'
+
+help ::
+	@echo '  help-onf-git        Display git makefile targets'
+
+# [EOF]
diff --git a/makefiles/git/include.mk b/makefiles/git/include.mk
new file mode 100644
index 0000000..9d2558c
--- /dev/null
+++ b/makefiles/git/include.mk
@@ -0,0 +1,37 @@
+# -*- makefile -*-
+# -----------------------------------------------------------------------
+# Copyright 2022-2023 Open Networking Foundation (ONF) and the ONF Contributors
+#
+# Licensed 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.
+#
+# SPDX-FileCopyrightText: 2022 Open Networking Foundation (ONF) and the ONF Contributors
+# SPDX-License-Identifier: Apache-2.0
+# -----------------------------------------------------------------------
+
+$(if $(DEBUG),$(warning ENTER))
+
+##--------------------##
+##---]  INCLUDES  [---##
+##--------------------##
+include $(ONF_MAKEDIR)/git/help.mk
+include $(ONF_MAKEDIR)/git/required.mk
+
+## Special snowflakes: per-repository logic
+-include $(ONF_MAKEDIR)/git/$(--repo-name--).mk
+
+ifdef USE-ONF-GIT-MK
+  # Dynamic loading when targets are requested by name
+  include $(ONF_MAKEDIR)/git/submodules.mk
+endif
+
+# [EOF]
diff --git a/makefiles/git/required.mk b/makefiles/git/required.mk
new file mode 100644
index 0000000..44f498d
--- /dev/null
+++ b/makefiles/git/required.mk
@@ -0,0 +1,32 @@
+# -*- makefile -*-
+# -----------------------------------------------------------------------
+# Copyright 2022-2023 Open Networking Foundation (ONF) and the ONF Contributors
+#
+# Licensed 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.
+# -----------------------------------------------------------------------
+# Intent: Conditionally load when named targets are requested.
+#   var ?= $(error ...) definitions are fatal to "make help" and others
+# -----------------------------------------------------------------------
+
+git-mk-targets := $(NULL)
+git-mk-targets := show-submodules
+
+# -----------------------------------------------------------------------
+# Define a flag to only load release targets when mentioned by name
+# Makefile can also explicitly define the flag to force always loading.
+# -----------------------------------------------------------------------
+$(foreach tgt,$(git-mk-targets),\
+  $(if $(findstring $(tgt),$(MAKECMDGOALS)),$(eval USE-ONF-GIT-MK := true))\
+)
+
+# [EOF]
diff --git a/makefiles/git/submodules.mk b/makefiles/git/submodules.mk
new file mode 100644
index 0000000..42c2fc2
--- /dev/null
+++ b/makefiles/git/submodules.mk
@@ -0,0 +1,57 @@
+# -*- makefile -*-
+# -----------------------------------------------------------------------
+# Copyright 2022-2023 Open Networking Foundation (ONF) and the ONF Contributors
+#
+# Licensed 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.
+#
+# SPDX-FileCopyrightText: 2022 Open Networking Foundation (ONF) and the ONF Contributors
+# SPDX-License-Identifier: Apache-2.0
+# -----------------------------------------------------------------------
+
+$(if $(DEBUG),$(warning ENTER))
+
+show-submodules:
+
+	$(HIDE)cat .gitmodules
+
+	@echo
+	$(HIDE) git submodule
+
+$(if $(DEBUG),$(warning LEAVE))
+
+# https://github.com/lfit/releng-global-jjb/tags
+# git checkout v0.86.7
+# [crucible:global-jjb] git checkout v0.86.7
+# Previous HEAD position was 5dc3432 Update regexp in lf-infra-ship-logs macro
+# HEAD is now at c5bd1d3 Fix: Pin urllib3~=1.26.15 in pypi dist jobs
+
+# 5dc3432cae2f13d9e5151a00a76a78ce73d92d70 global-jjb (v0.53.3)
+# 0d88f8b7a24b53b1c3e189e30ab94373c51eea91 lf-ansible (0d88f8b)
+# 4a5b0cd9032938194c4813fe36663ddee4f9e60e packer/common-packer (v0.1.0~22)
+
+# https://stackoverflow.com/questions/30301510/git-submodule-specify-version
+# cd global-jjb
+# git checkout v0.86.7
+# cd -
+# git commit . -m "use submodule v0.86.7"
+
+# https://github.com/lfit/releng-lf-ansible.git
+# tag==master, no release
+
+# https://github.com/lfit/releng-common-packer.git
+# cd packer/common-packer
+# git checkout v0.12.1
+# cd -
+# git commit . -m "use submodule v0.12.1""
+
+# [EOF]
diff --git a/makefiles/golang/include.mk b/makefiles/golang/include.mk
new file mode 100644
index 0000000..1ce3d7f
--- /dev/null
+++ b/makefiles/golang/include.mk
@@ -0,0 +1,26 @@
+# -*- makefile -*-
+# -----------------------------------------------------------------------
+# Copyright 2023 Open Networking Foundation (ONF) and the ONF Contributors
+#
+# Licensed 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.
+# -----------------------------------------------------------------------
+# SPDX-FileCopyrightText: 2017-2023 Open Networking Foundation (ONF) and the ONF Contributors
+# SPDX-License-Identifier: Apache-2.0
+# -----------------------------------------------------------------------
+# https://gerrit.opencord.org/plugins/gitiles/onf-make
+# ONF.makefiles.include.version = 1.1
+# -----------------------------------------------------------------------
+
+include $(ONF_MAKEDIR)/golang/mod-update.mk
+
+# [EOF]
diff --git a/makefiles/golang/mod-update.mk b/makefiles/golang/mod-update.mk
new file mode 100644
index 0000000..5212a47
--- /dev/null
+++ b/makefiles/golang/mod-update.mk
@@ -0,0 +1,60 @@
+# -*- makefile -*-
+# -----------------------------------------------------------------------
+# Copyright 2017-2023 Open Networking Foundation (ONF) and the ONF Contributors
+#
+# Licensed 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.
+# -----------------------------------------------------------------------
+# SPDX-FileCopyrightText: 2017-2023 Open Networking Foundation (ONF) and the ONF Contributors
+# SPDX-License-Identifier: Apache-2.0
+# -----------------------------------------------------------------------
+# https://gerrit.opencord.org/plugins/gitiles/onf-make
+# ONF.makefiles.include.version = 1.1
+# -----------------------------------------------------------------------
+
+## -----------------------------------------------------------------------
+## -----------------------------------------------------------------------
+## if dev-mode: make LOCAL_FIX_PERMS=1 mod-update
+.PHONY: mod-update
+mod-update: mod-tidy mod-vendor
+
+## -----------------------------------------------------------------------
+## -----------------------------------------------------------------------
+.PHONY: mod-tidy
+mod-tidy :
+	$(call banner-enter,Target $@)
+	${GO} mod tidy
+	$(call banner-leave,Target $@)
+
+## -----------------------------------------------------------------------
+## -----------------------------------------------------------------------
+.PHONY: mod-vendor
+mod-vendor : mod-tidy
+mod-vendor :
+	$(call banner-enter,Target $@)
+	$(if $(LOCAL_FIX_PERMS),chmod o+w $(CURDIR))
+	${GO} mod vendor
+	$(if $(LOCAL_FIX_PERMS),chmod o-w $(CURDIR))
+	$(call banner-leave,Target $@)
+
+## -----------------------------------------------------------------------
+## -----------------------------------------------------------------------
+help ::
+	@echo '  mod-update             mod-tidy & mod-update'
+	@echo '  mod-tidy               go mod tidy'
+	@echo '  mod-vendor             go mod vendor'
+
+  ifdef VERBOSE
+	@echo '    LOCAL_FIX_PERMS=1    Local hack to fix docker uid/gid volume problem'
+  endif
+
+# [EOF]
diff --git a/makefiles/include.mk b/makefiles/include.mk
index 2768172..4df4c4c 100644
--- a/makefiles/include.mk
+++ b/makefiles/include.mk
@@ -18,9 +18,11 @@
 # SPDX-License-Identifier: Apache-2.0
 # -----------------------------------------------------------------------
 # https://gerrit.opencord.org/plugins/gitiles/onf-make
-# ONF.makefile.version = 1.0
+# ONF.makefiles.include.version = 1.1
 # -----------------------------------------------------------------------
 
+ifndef mk-include--onf-make # single-include guard macro
+
 $(if $(DEBUG),$(warning ENTER))
 
 ## -----------------------------------------------------------------------
@@ -31,19 +33,25 @@
 onf-mk-top    := $(subst /include.mk,$(null),$(onf-mk-abs))
 ONF_MAKEDIR   := $(onf-mk-top)
 
-MAKEDIR ?= $(ONF_MAKEDIR)#                   # Two dirs needed, local and common
+TOP ?= $(patsubst %/makefiles/include.mk,%,$(onf-mk-abs))
 
 include $(ONF_MAKEDIR)/consts.mk
 include $(ONF_MAKEDIR)/help/include.mk       # render target help
 include $(ONF_MAKEDIR)/utils/include.mk      # dependency-less helper macros
 include $(ONF_MAKEDIR)/etc/include.mk        # banner macros
-
 include $(ONF_MAKEDIR)/commands/include.mk   # Tools and local installers
 
 include $(ONF_MAKEDIR)/virtualenv.mk#        # lint-{jjb,python} depends on venv
+include $(ONF_MAKEDIR)/patches/include.mk#   # Patch when python 3.10+ in use
 include $(ONF_MAKEDIR)/lint/include.mk
-# include $(ONF_MAKEDIR)/git-submodules.mk
-# include $(ONF_MAKEDIR)/gerrit/include.mk
+
+include $(ONF_MAKEDIR)/gerrit/include.mk
+include $(ONF_MAKEDIR)/git/include.mk
+include $(ONF_MAKEDIR)/golang/include.mk
+include $(ONF_MAKEDIR)/jjb/include.mk
+
+$(if $(USE-VOLTHA-RELEASE-MK),\
+  $(eval include $(ONF_MAKEDIR)/release/include.mk))
 
 include $(ONF_MAKEDIR)/todo.mk
 include $(ONF_MAKEDIR)/help/variables.mk
@@ -51,24 +59,18 @@
 ##---------------------##
 ##---]  ON_DEMAND  [---##
 ##---------------------##
-$(if $(USE_DOCKER_MK),$(eval $(ONF_MAKEDIR)/docker/include.mk))
+$(if $(USE-ONF-GERRIT-MK),$(eval include $(ONF_MAKEDIR)/gerrit/include.mk))
+$(if $(USE-ONF-DOCKER-MK),$(eval include $(ONF_MAKEDIR)/docker/include.mk))
 
 ##-------------------##
 ##---]  TARGETS  [---##
 ##-------------------##
-include $(ONF_MAKEDIR)/targets/clean.mk
-# include $(ONF_MAKEDIR)/targets/check.mk
-include $(ONF_MAKEDIR)/targets/sterile.mk
-# include $(ONF_MAKEDIR)/targets/test.mk
+include $(ONF_MAKEDIR)/targets/include.mk # clean, sterile
 
 $(if $(DEBUG),$(warning LEAVE))
 
-## --------------------------------------------------------------------------
-## structure to support pre/post target handling w/o inlining in Makefile (?)
-## --------------------------------------------------------------------------
-##   include makefiles/include.mk
-##     include makefiles/main/enter.mk
-##     [... include *.mk ...]
-##     include makefiles/main/leave.mk
+mk-include--onf-make := true
+
+endif # mk-include--onf-make
 
 # [EOF]
diff --git a/makefiles/jjb/help.mk b/makefiles/jjb/help.mk
new file mode 100644
index 0000000..331c68a
--- /dev/null
+++ b/makefiles/jjb/help.mk
@@ -0,0 +1,38 @@
+# -*- makefile -*-
+# -----------------------------------------------------------------------
+# Copyright 2022-2023 Open Networking Foundation (ONF) and the ONF Contributors
+#
+# Licensed 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.
+# -----------------------------------------------------------------------
+# Intent: Helper makefile target used to setup for a release
+# -----------------------------------------------------------------------
+
+## ---------------------------------------------------------------------------
+## Intent: Display supported targets
+## ---------------------------------------------------------------------------
+help-jjb:
+	@echo
+	@echo '[JJB]'
+	@echo '  jjb-gen             Generate a local set of JJB pipelines'
+
+  ifdef VERBOSE
+	@echo '    LOGS=1            Display log from jjb-gen target'
+	@echo '    VERBOSE=1         Display generated pipeline files'
+  endif
+
+## ---------------------------------------------------------------------------
+## ---------------------------------------------------------------------------
+help ::
+	@echo '  help-jjb            Display Jenkins Job Builder targets'
+
+# [EOF]
diff --git a/makefiles/jjb/include.mk b/makefiles/jjb/include.mk
new file mode 100644
index 0000000..7d213b4
--- /dev/null
+++ b/makefiles/jjb/include.mk
@@ -0,0 +1,36 @@
+# -*- makefile -*-
+# -----------------------------------------------------------------------
+# Copyright 2022-2023 Open Networking Foundation (ONF) and the ONF Contributors
+#
+# Licensed 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.
+#
+# SPDX-FileCopyrightText: 2022 Open Networking Foundation (ONF) and the ONF Contributors
+# SPDX-License-Identifier: Apache-2.0
+# -----------------------------------------------------------------------
+
+$(if $(DEBUG),$(warning ENTER))
+
+##--------------------##
+##---]  INCLUDES  [---##
+##--------------------##
+include $(ONF_MAKEDIR)/jjb/help.mk
+include $(ONF_MAKEDIR)/jjb/required.mk
+
+ifdef USE-ONF-JJB-MK
+  # Dynamic loading when targets are requested by name
+  include $(ONF_MAKEDIR)/jjb/targets.mk
+endif
+
+# [EOF]
+
+
diff --git a/makefiles/jjb/required.mk b/makefiles/jjb/required.mk
new file mode 100644
index 0000000..17371e9
--- /dev/null
+++ b/makefiles/jjb/required.mk
@@ -0,0 +1,33 @@
+# -*- makefile -*-
+# -----------------------------------------------------------------------
+# Copyright 2022-2023 Open Networking Foundation (ONF) and the ONF Contributors
+#
+# Licensed 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.
+# -----------------------------------------------------------------------
+# Intent: Conditionally load when named targets are requested.
+#   var ?= $(error ...) definitions are fatal to "make help" and others
+# -----------------------------------------------------------------------
+
+onf-mk-jjb-targets := $(NULL)
+onf-mk-jjb-targets += jjb-gen
+onf-mk-jjb-targets += sterile
+
+# -----------------------------------------------------------------------
+# Define a flag to only load release targets when mentioned by name
+# Makefile can also explicitly define the flag to force always loading.
+# -----------------------------------------------------------------------
+$(foreach tgt,$(onf-mk-jjb-targets),\
+  $(if $(findstring $(tgt),$(MAKECMDGOALS)),$(eval USE-ONF-JJB-MK := true))\
+)
+
+# [EOF]
diff --git a/makefiles/jjb/targets.mk b/makefiles/jjb/targets.mk
new file mode 100644
index 0000000..730d229
--- /dev/null
+++ b/makefiles/jjb/targets.mk
@@ -0,0 +1,65 @@
+# -*- makefile -*-
+# -----------------------------------------------------------------------
+# Copyright 2022-2023 Open Networking Foundation (ONF) and the ONF Contributors
+#
+# Licensed 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.
+# -----------------------------------------------------------------------
+# Intent: Helper makefile target used to setup for a release
+# -----------------------------------------------------------------------
+
+$(if $(DEBUG),$(warning ENTER))
+
+##-------------------##
+##---]  GLOBALS  [---##
+##-------------------##
+jjb-gen-dir := build
+
+##-------------------##
+##---]  TARGETS  [---##
+##-------------------##
+all: help
+
+## -----------------------------------------------------------------------
+## Intent: Generate pipeline jobs
+## -----------------------------------------------------------------------
+.PHONY: jjb-gen
+
+jjb-gen-log := $(jjb-gen-dir)/jjb-gen.log
+jjb-gen:
+	$(call banner-enter,Target $@)
+	@mkdir -p $(jjb-gen-dir)
+	@touch "$(jjb-gen-dir)/.sentinel"
+	( $(activate) \
+	   && jenkins-jobs test $(PWD)/jjb -o $(jjb-gen-dir) 3>&1 2>&1 \
+	) | tee "$(jjb-gen-log)"
+
+  ifdef LOGS
+	-@less "$(jjb-gen-log)"
+  endif
+
+  ifdef VERBOSE
+	@echo
+	@echo "** Display generated pipelines"
+	find "$(jjb-gen-dir)" -newer "$(jjb-gen-dir)/.sentinel" -ls
+  endif
+
+	$(call banner-leave,Target $@)
+
+## -----------------------------------------------------------------------
+## -----------------------------------------------------------------------
+sterile ::
+	$(RM) -r $(jjb-gen-dir)
+
+$(if $(DEBUG),$(warning LEAVE))
+
+# [EOF]
diff --git a/makefiles/lint/doc8/include.mk b/makefiles/lint/doc8/include.mk
index 86f9677..23f7b0b 100644
--- a/makefiles/lint/doc8/include.mk
+++ b/makefiles/lint/doc8/include.mk
@@ -49,7 +49,7 @@
 	$(activate) && doc8 --version
 	@echo
 	$(activate) && doc8 $(lint-doc8-excl)
-	$(call banner-leave,Target $@)
+	$(call banner-enter,Target $@)
 
 ## -----------------------------------------------------------------------
 ## Intent: Display command usage
diff --git a/makefiles/lint/docker/get.sh b/makefiles/lint/docker/get.sh
new file mode 100644
index 0000000..4e4a7f6
--- /dev/null
+++ b/makefiles/lint/docker/get.sh
@@ -0,0 +1,64 @@
+#!/bin/bash
+# -----------------------------------------------------------------------
+# Copyright 2023 Open Networking Foundation (ONF) and the ONF Contributors
+#
+# Licensed 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.
+#
+# SPDX-FileCopyrightText: 2023 Open Networking Foundation (ONF) and the ONF Contributors
+# SPDX-License-Identifier: Apache-2.0
+# -----------------------------------------------------------------------
+
+## -----------------------------------------------------------------------
+## Intent: Install a bbsim binary for local development use.
+## -----------------------------------------------------------------------
+## Note: A python or golang script may be a simpler answer.
+##       Interpreter modules provide answers for uname -{a,m,o}
+##       with dictionary translation into needed values.
+## -----------------------------------------------------------------------
+
+# import platform
+# platform.processor()
+# platform.system        # Windows
+
+# lshw:    width: 64 bits
+
+# >>> import platform
+# >>> platform.machine()
+# 'x86'
+
+
+# $ uname -m
+# armv7l
+
+## which arch
+# https://github.com/hadolint/hadolint/releases/tag/v2.12.0
+case "$(uname -a)" in
+    *x86_64*)
+esac
+
+os=''
+case "$(uname -o)" in
+    *Linux*) os='Linux'
+esac
+
+
+# hadolint-Darwin-x86_64
+# hadolint-Darwin-x86_64.sha256
+# hadolint-Linux-arm64
+# hadolint-Linux-arm64.sha256
+# hadolint-Linux-x86_64
+# hadolint-Linux-x86_64.sha256
+# hadolint-Windows-x86_64.exe
+# hadolint-Windows-x86_64.exe.sha256
+# Source code (zip)
+# Source code (tar.gz)
diff --git a/makefiles/lint/docker/hadolint.mk b/makefiles/lint/docker/hadolint.mk
new file mode 100644
index 0000000..eb182f7
--- /dev/null
+++ b/makefiles/lint/docker/hadolint.mk
@@ -0,0 +1,80 @@
+# -*- makefile -*-
+# -----------------------------------------------------------------------
+# Copyright 2017-2023 Open Networking Foundation (ONF) and the ONF Contributors
+#
+# Licensed 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.
+# -----------------------------------------------------------------------
+
+##-------------------##
+##---]  GLOBALS  [---##
+##-------------------##
+
+HADOLINT = $(docker-run-app) $(is-stdin) $(vee-citools)-hadolint hadolint
+
+ifdef LOCAL_LINT
+  lint-hadolint-dep = lint-hadolint-local
+else
+  lint-hadolint-dep = lint-hadolint
+endif
+
+## -----------------------------------------------------------------------
+## -----------------------------------------------------------------------
+.PHONY: $(lint-hadolint-dep)
+
+lint : $(lint-hadolint-dep)
+
+lint-dockerfile : $(lint-hadolint-dep)
+
+## -----------------------------------------------------------------------
+## -----------------------------------------------------------------------
+lint-hadolint:
+
+	@echo
+	@echo '** -------------------------------------------------------------'
+	@echo "** $(MAKE): processing target [$@]"
+	@echo '** -------------------------------------------------------------'
+	$(HIDE)${HADOLINT} $$(find ./build -name "Dockerfile*")
+	@echo "Dockerfile lint check OK"
+
+## -----------------------------------------------------------------------
+## -----------------------------------------------------------------------
+hadolint-cmd := ./hadolint-Linux-x86_64
+
+lint-hadolint-local: hadolint-get
+	$(hadolint-cmd) $$(find ./build -name "Dockerfile*")
+
+## -----------------------------------------------------------------------
+## Intent: Retrieve the hadolint tool
+## https://github.com/hadolint/hadolint/releases/tag/v2.12.0
+## -----------------------------------------------------------------------
+hadolint-get:
+	true
+#	$(MAKECMDGOALS)/lint/docker/get.sh
+#	$(GIT) clone https://github.com/hadolint/hadolint.git
+#	wget https://github.com/hadolint/hadolint/releases/download/v2.12.0/hadolint-Linux-x86_64
+
+## -----------------------------------------------------------------------
+## -----------------------------------------------------------------------
+help ::
+	@echo '  lint-dockerfile      Perform all dockerfile lint checks'
+	@echo '  lint-hadolint        Dockerfile lint check'
+
+## -----------------------------------------------------------------------
+## -----------------------------------------------------------------------
+todo ::
+	@echo '  o Update lint-dockerfile to run all dockerfile lint checks'
+
+# [SEE ALSO]
+# https://github.com/hadolint/hadolint
+
+# [EOF]
diff --git a/makefiles/lint/docker/include.mk b/makefiles/lint/docker/include.mk
new file mode 100644
index 0000000..9d6b4d0
--- /dev/null
+++ b/makefiles/lint/docker/include.mk
@@ -0,0 +1,70 @@
+# -*- makefile -*-
+# -----------------------------------------------------------------------
+# Copyright 2017-2023 Open Networking Foundation
+#
+# Licensed 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.
+# -----------------------------------------------------------------------
+
+
+##-------------------##
+##---]  GLOBALS  [---##
+##-------------------##
+.PHONY: lint-hadolint lint-hadolint-all lint-hadolint-modified
+
+## -----------------------------------------------------------------------
+## -----------------------------------------------------------------------
+ifndef NO-LINT-HADOLINT
+  have-rst-files := $(if $(strip $(RST_SOURCE)),true)
+  RST_SOURCE     ?= $(error RST_SOURCE= is required)
+
+  lint-hadolint-mode := $(if $(have-hadolint-files),modified,all)
+  lint : lint-hadolint-$(lint-hadolint-mode)
+endif# NO-LINT-HADOLINT
+
+# Consistent targets across lint makefiles
+lint-hadolint-all      : lint-hadolint
+lint-hadolint-modified : lint-hadolint
+
+## -----------------------------------------------------------------------
+## -----------------------------------------------------------------------
+include $(MAKEDIR)/lint/hadolint/excl.mk
+
+ifdef lint-hadolint-excl
+  lint-hadolint-excl-args += $(addprefix --ignore-path$(space),$(lint-hadolint-excl))
+endif
+lint-hadolint-excl-args += $(addprefix --ignore-path$(space),$(lint-hadolint-excl-raw))
+
+lint-hadolint-args += --max-line-length 120
+
+lint-hadolint: $(venv-activate-script)
+	@echo
+	@echo '** -----------------------------------------------------------------------'
+	@echo '** hadolint *.rst syntax checking'
+	@echo '** -----------------------------------------------------------------------'
+	$(activate) && hadolint --version
+	@echo
+	$(activate) && hadolint $(lint-hadolint-excl-args) $(lint-hadolint-args) .
+
+## -----------------------------------------------------------------------
+## Intent: Display command usage
+## -----------------------------------------------------------------------
+help::
+	@echo '  lint-hadolint          Syntax check python using the hadolint command'
+  ifdef VERBOSE
+	@echo '  lint-hadolint-all       hadolint checking: exhaustive'
+	@echo '  lint-hadolint-modified  hadolint checking: only modified'
+  endif
+
+# include $(MAKEDIR)/lint/docker/hadolint.mk
+
+# [EOF]
diff --git a/makefiles/help.mk b/makefiles/lint/hadolint/excl.mk
similarity index 72%
copy from makefiles/help.mk
copy to makefiles/lint/hadolint/excl.mk
index c272d96..cc4b4af 100644
--- a/makefiles/help.mk
+++ b/makefiles/lint/hadolint/excl.mk
@@ -1,6 +1,5 @@
-# -*- makefile -*-
 # -----------------------------------------------------------------------
-# Copyright 2017-2024 Open Networking Foundation (ONF) and the ONF Contributors
+# Copyright 2023 Open Networking Foundation (ONF) and the ONF Contributors
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -15,9 +14,4 @@
 # limitations under the License.
 # -----------------------------------------------------------------------
 
-# Parent makefile should include this early so help
-# message will be prefixed by a usage statement.
-help ::
-	@echo "Usage: $(MAKE) [options] [target] ..."
-
 # [EOF]
diff --git a/makefiles/lint/license/include.mk b/makefiles/lint/license/include.mk
index c3569f3..431e45e 100644
--- a/makefiles/lint/license/include.mk
+++ b/makefiles/lint/license/include.mk
@@ -15,21 +15,27 @@
 # limitations under the License.
 # -----------------------------------------------------------------------
 
-ifndef mk-include--onf-lint-license#       # one-time loader
-ifndef NO-LINT-LICENSE
+##-------------------##
+##---]  GLOBALS  [---##
+##-------------------##
 
-$(if $(DEBUG),$(warning ENTER))
+##-------------------##
+##---]  TARGETS  [---##
+##-------------------##
+ifndef NO-LINT-REUSE
+  lint : lint-license
+endif
 
-$(if $(USE_LINT_LICENSE)\
-  ,$(eval include $(ONF_MAKEDIR)/lint/license/voltha-system-tests/include.mk)\
-  ,$(eval include $(ONF_MAKEDIR)/lint/license/common.mk)\
-)
+## -----------------------------------------------------------------------
+## Intent: Perform a lint check on makefile sources
+## -----------------------------------------------------------------------
+lint-license:
+	reuse --root . lint
 
-  mk-include--onf-lint-license := true
-
-$(if $(DEBUG),$(warning LEAVE))
-
-endif # NO-LINT-LICENSE
-endif # mk-include--onf-lint-license
+## -----------------------------------------------------------------------
+## Intent: Display command help
+## -----------------------------------------------------------------------
+help-summary ::
+	@echo '  lint-reuse              License syntax checking'
 
 # [EOF]
diff --git a/makefiles/lint/license/license-check.sh b/makefiles/lint/license/license-check.sh
index 73f72db..04978cf 100755
--- a/makefiles/lint/license/license-check.sh
+++ b/makefiles/lint/license/license-check.sh
@@ -1,5 +1,4 @@
 #!/usr/bin/env bash
-
 # -----------------------------------------------------------------------
 # Copyright 2022-2024 Open Networking Foundation (ONF) and the ONF Contributors
 #
@@ -156,10 +155,12 @@
   ! -path "*/docs/*" \
   ! -name 'output.xml' \
   ! -path "*/vst_venv/*" \
+  ! -path '*/\.venv/*' \
   ! -name '*#*' \
   ! -path '*scripts/flog/*' \
   ! -name '*~' \
   ! -name 'VERSION' \
+  ! -name 'kail' \
   ! -name 'patch' \
   -print0 )
 
diff --git a/makefiles/lint/license/voltha-system-tests/include.mk b/makefiles/lint/license/voltha-system-tests/include.mk
index ebbeb90..55ffedb 100644
--- a/makefiles/lint/license/voltha-system-tests/include.mk
+++ b/makefiles/lint/license/voltha-system-tests/include.mk
@@ -15,11 +15,19 @@
 # limitations under the License.
 # -----------------------------------------------------------------------
 
+<<<<<<< HEAD
 .PHONY: lint-license-vst
 
 ## -----------------------------------------------------------------------
 ## -----------------------------------------------------------------------
 lint : lint-license-vst
+=======
+.PHONY: lint-license
+
+## -----------------------------------------------------------------------
+## -----------------------------------------------------------------------
+lint : lint-license
+>>>>>>> dc6caae ([VOL-5064] - Build and deploy voltha-system-tests)
 
 lint-license-gargs += --recursive
 
@@ -38,7 +46,11 @@
 
 # TODO: Normalize into .venv for consistent filtering across projects.
 lint-license-gargs += --exclude-dir='.git'
+<<<<<<< HEAD
 lint-license-gargs += --exclude-dir='vst_venv'
+=======
+lint-license-gargs += --exclude-dir='$(venv-name)'
+>>>>>>> dc6caae ([VOL-5064] - Build and deploy voltha-system-tests)
 lint-license-gargs += --exclude-dir='flog'
 
 lint-license-gargs += --exclude='*.json'
@@ -68,7 +80,11 @@
 ## -----------------------------------------------------------------------
 ## Jenkins job checking logic.
 ## -----------------------------------------------------------------------
+<<<<<<< HEAD
 lint-license-vst:
+=======
+lint-license:
+>>>>>>> dc6caae ([VOL-5064] - Build and deploy voltha-system-tests)
 	$(MAKEDIR)/lint/license/license-check.sh
 
 ## -----------------------------------------------------------------------
diff --git a/makefiles/lint/license/voltha-system-tests/license-check.sh b/makefiles/lint/license/voltha-system-tests/license-check.sh
index 7a9deb9..99fc07f 100755
--- a/makefiles/lint/license/voltha-system-tests/license-check.sh
+++ b/makefiles/lint/license/voltha-system-tests/license-check.sh
@@ -37,9 +37,12 @@
 ## the only question mark.
 ## ---------------------------------------------------------------------------
 
+<<<<<<< HEAD
 echo "BLAH"
 exit 1
 
+=======
+>>>>>>> dc6caae ([VOL-5064] - Build and deploy voltha-system-tests)
 set +e -u -o pipefail
 fail_licensecheck=0
 
@@ -54,17 +57,24 @@
 
 while IFS= read -r -d '' path
 do
+<<<<<<< HEAD
     case "$path" in
 	*venv*) echo "GERR: $path"
 		exit 1
 		;;
     esac
+=======
+>>>>>>> dc6caae ([VOL-5064] - Build and deploy voltha-system-tests)
     if ! grep -q "${gargs[@]}" "${path}";
     then
 	echo "ERROR: $path does not contain License Header"
 	fail_licensecheck=1
     fi
+<<<<<<< HEAD
 done < <(find . \( -name ".git" -o -name '.venv' -o 'vst_venv' \) -prune -o -type f \
+=======
+done < <(find . -name ".git" -prune -o -type f \
+>>>>>>> dc6caae ([VOL-5064] - Build and deploy voltha-system-tests)
   ! -iname "*.png" \
   ! -name "*.asc" \
   ! -name "*.bat" \
@@ -155,8 +165,13 @@
   ! -name "*.pb.h" \
   ! -name "*.pb.cc" \
   ! -path "*/docs/*" \
+<<<<<<< HEAD
   ! -name 'output.xml' \
   ! -path "*/vst_venv/*" \
+=======
+  ! -name 'output.xml' \ 
+  ! -path "*/.venv/*" \
+>>>>>>> dc6caae ([VOL-5064] - Build and deploy voltha-system-tests)
   ! -name '*#*' \
   ! -path '*scripts/flog/*' \
   ! -name '*~' \
diff --git a/makefiles/lint/markdown/include.mk b/makefiles/lint/markdown/include.mk
new file mode 100644
index 0000000..26ebf43
--- /dev/null
+++ b/makefiles/lint/markdown/include.mk
@@ -0,0 +1,62 @@
+# -*- makefile -*-
+# -----------------------------------------------------------------------
+# Copyright 2017-2022 Open Networking Foundation
+#
+# Licensed 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.
+# -----------------------------------------------------------------------
+
+##-------------------##
+##---]  GLOBALS  [---##
+##-------------------##
+.PHONY: lint-mdl lint-mdl-all lint-mdl-modified
+
+have-rst-files := $(if $(strip $(RST_SOURCE)),true)
+RST_SOURCE     ?= $(error RST_SOURCE= is required)
+
+## -----------------------------------------------------------------------
+## -----------------------------------------------------------------------
+ifndef NO-LINT-MARKDOWN
+  lint-mdl-mode := $(if $(have-mdl-files),modified,all)
+  lint : lint-mdl-$(lint-mdl-mode)
+endif# NO-LINT-MDL
+
+# Consistent targets across lint makefiles
+lint-mdl-all      : lint-mdl
+lint-mdl-modified : lint-mdl
+
+# onf-excl-dirs
+LINT_STYLE ?= mdl_strict.rb
+
+mdl-excludes := $(foreach path,$(onf-exclude-dirs),! -path "./$(path)/*")
+
+lint-mdl:
+	$(call banner-enter,Target $@)
+	@echo "markdownlint(mdl) version: `mdl --version`"
+	@echo "style config:"
+	@echo "---"
+	@cat $(LINT_STYLE)
+	@echo "---"
+# 	mdl -s $(LINT_STYLE) `find -L $(SOURCEDIR) ! -path "./_$(venv-activate-script)/*" ! -path "./_build/*" ! -path "./repos/*" ! -path "*vendor*" -name "*.md"`
+	mdl -s $(LINT_STYLE) `find -L $(SOURCEDIR) $(mdl-excludes) -iname "*.md"`
+
+## -----------------------------------------------------------------------
+## Intent: Display command usage
+## -----------------------------------------------------------------------
+help::
+	@echo '  lint-mdl          Syntax check python using the mdl command'
+  ifdef VERBOSE
+	@echo '  lint-mdl-all       mdl checking: exhaustive'
+	@echo '  lint-mdl-modified  mdl checking: only modified'
+  endif
+
+# [EOF]
diff --git a/makefiles/lint/markdown/urls b/makefiles/lint/markdown/urls
new file mode 100644
index 0000000..86ff76b
--- /dev/null
+++ b/makefiles/lint/markdown/urls
@@ -0,0 +1,6 @@
+# -*- makefile -*-
+
+# Consumer: repo:voltha-docs
+https://github.com/markdownlint/markdownlint
+
+# [EOF]
diff --git a/makefiles/lint/python/find_utils.mk b/makefiles/lint/python/find_utils.mk
new file mode 100644
index 0000000..7ab4c4f
--- /dev/null
+++ b/makefiles/lint/python/find_utils.mk
@@ -0,0 +1,32 @@
+# -*- makefile -*-
+# -----------------------------------------------------------------------
+# Intent:
+#   o Construct a find command able to gather python files with filtering.
+#   o Used by library makefiles flake8.mk and pylint.mk for iteration.
+# -----------------------------------------------------------------------
+
+## -----------------------------------------------------------------------
+## Intent: Construct a string for invoking find \( excl-pattern \) -prune
+# -----------------------------------------------------------------------
+gen-python-find-excl = \
+  $(strip \
+	-name '__ignored__' \
+	$(foreach dir,$($(1)),-o -name $(dir)) \
+  )
+
+## -----------------------------------------------------------------------
+## Intent: Construct a find command to gather a list of python files
+##         with exclusions.
+## -----------------------------------------------------------------------
+## Usage:
+#	$(activate) & $(call gen-python-find-cmd) | $(args-n1) pylint
+## -----------------------------------------------------------------------
+gen-python-find-cmd = \
+  $(strip \
+    find . \
+      \( $(call gen-python-find-excl,onf-excl-dirs) \) -prune \
+      -o -name '*.py' \
+      -print0 \
+  )
+
+# [EOF]
diff --git a/makefiles/lint/python/flake8 b/makefiles/lint/python/flake8
index 4283c3c..763b942 100644
--- a/makefiles/lint/python/flake8
+++ b/makefiles/lint/python/flake8
@@ -21,9 +21,8 @@
 
 lint : lint-python
 
-lint-python: vst_venv
-	-source ./$</bin/activate \
-	    && set -u \
+lint-python: $(venv-activate-script)
+	-$(activate) \
 	    && pylint $(PYTHON_FILES) \
 	    && flake8 --max-line-length=99 --count $(PYTHON_FILE)S
 
diff --git a/makefiles/lint/python/flake8.mk b/makefiles/lint/python/flake8.mk
index 7a36aaf..6b2b561 100644
--- a/makefiles/lint/python/flake8.mk
+++ b/makefiles/lint/python/flake8.mk
@@ -2,7 +2,7 @@
 # -----------------------------------------------------------------------
 # Copyright 2022-2024 Open Networking Foundation (ONF) and the ONF Contributors
 #
-# Licensed under the Apache License, Version 2.0 (the "License");
+# Licensed 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
 #
@@ -15,35 +15,80 @@
 # limitations under the License.
 # -----------------------------------------------------------------------
 
+$(if $(DEBUG),$(warning ENTER))
+
 ##-------------------##
 ##---]  GLOBALS  [---##
 ##-------------------##
+.PHONY: lint-flake8 lint-flake8-all lint-flake8-modified
 
-# Gather sources to check
-# TODO: implement deps, only check modified files
-python-check-find := find . -name '*venv*' -prune\
-  -o \( -name '*.py' \)\
-  -type f -print0
-
-##-------------------##
-##---]  TARGETS  [---##
-##-------------------##
-ifndef NO-LINT-PYTHON-FLAKE8
-  lint        : lint-python-flake8
-  lint-python : lint-python-flake8
-endif
+PYTHON_FILES      ?= $(error PYTHON_FILES= required)
 
 ## -----------------------------------------------------------------------
-## Intent: Perform a lint check on makefile sources
+## Intent: Use the flake8 command to perform syntax checking.
+## Usage:
+##   % make lint
+##   % make lint-flake8-all
 ## -----------------------------------------------------------------------
-lint-python-flake8:
-	$(HIDE)$(env-clean) $(python-check-find) \
+ifndef NO-LINT-FLAKE8
+  lint-flake8-mode := $(if $(have-python-files),modified,all)
+  lint        : lint-flake8
+  lint-flake8 : lint-flake8-$(lint-flake8-mode)
+endif# NO-LINT-FLAKE8
+
+## -----------------------------------------------------------------------
+## Intent: exhaustive flake8 syntax checking
+## -----------------------------------------------------------------------
+# Construct: find . \( -name '__ignored__' -o -name dir -o name dir \)
+# flake8-find-filter := $(null)
+# flake8-find-filter += -name '__ignored__'#    # for alignment
+# flake8-find-filter += $(foreach dir,$(onf-excl-dirs),-o -name $(dir)))
+
+lint-flake8-all: $(venv-activate-script)
+	$(HIDE)$(MAKE) --no-print-directory lint-flake8-install
+
+	$(activate) && $(call gen-python-find-cmd) \
 	    | $(xargs-n1) flake8 --max-line-length=99 --count
 
+#  && find . \( $(flake8-find-filter) \) -prune -o -name '*.py' -print0 \
+# 	| $(xargs-n1) flake8 --max-line-length=99 --count
+
 ## -----------------------------------------------------------------------
-## Intent: Display command help
+## Intent: check deps for format and python3 cleanliness
+## Note:
+##   pylint --py3k option no longer supported
 ## -----------------------------------------------------------------------
-help-summary ::
-	@echo '  lint-python-flake8  Syntax check python sources (*.py)'
+lint-flake8-modified: $(venv-activate-script)
+	$(HIDE)$(MAKE) --no-print-directory lint-flake8-install
+
+	$(activate)\
+ && flake8 --max-line-length=99 --count $(PYTHON_FILES)
+
+## -----------------------------------------------------------------------
+## Intent:
+## -----------------------------------------------------------------------
+.PHONY: lint-flake8-install
+lint-flake8-install: $(venv-activate-script)
+	@echo
+	@echo "** -----------------------------------------------------------------------"
+	@echo "** python flake8 syntax checking"
+	@echo "** -----------------------------------------------------------------------"
+	$(activate) && pip install --upgrade flake8
+	$(activate) && flake8 --version
+	@echo
+
+## -----------------------------------------------------------------------
+## Intent: Display command usage
+## -----------------------------------------------------------------------
+help::
+	@echo '  lint-flake8          Syntax check python using the flake8 command'
+  ifdef VERBOSE
+	@echo '  $(MAKE) lint-pylint PYTHON_FILES=...'
+	@echo '  lint-flake8-modified  flake8 checking: only modified'
+	@echo '  lint-flake8-all       flake8 checking: exhaustive'
+	@echo '  lint-flake8-install   Install the flake8 command'
+  endif
+
+$(if $(DEBUG),$(warning LEAVE))
 
 # [EOF]
diff --git a/makefiles/lint/python/include.mk b/makefiles/lint/python/include.mk
index b052d84..57dfd8b 100644
--- a/makefiles/lint/python/include.mk
+++ b/makefiles/lint/python/include.mk
@@ -15,31 +15,17 @@
 # limitations under the License.
 # -----------------------------------------------------------------------
 
-ifndef mk-include--onf-lint-python#       # one-time loader
-
 $(if $(DEBUG),$(warning ENTER))
 
-## -----------------------------------------------------------------------
-## Intent: Display early so lint targets are grouped
-## -----------------------------------------------------------------------
-help ::
-#	@echo
-#	@echo '[PYTHON]'
-	@echo '  lint-python         Syntax check python sources (*.py)'
-#	@echo '  help-lint-python-flake8'
-#	@echo '  help-lint-python-pylint'
+##-------------------##
+##---]  GLOBALS  [---##
+##-------------------##
+$(if $(UNSTABLE),$(eval lint-python-all := true))
 
-## -----------------------------------------------------------------------
-## -----------------------------------------------------------------------
-  ifndef NO-LINT-PYTHON
-    include $(ONF_MAKEDIR)/lint/python/flake8.mk
-    include $(ONF_MAKEDIR)/lint/python/pylint.mk
-  endif
-
-  mk-include--onf-lint-python := true
+include $(ONF_MAKEDIR)/lint/python/find_utils.mk
+include $(ONF_MAKEDIR)/lint/python/flake8.mk
+include $(ONF_MAKEDIR)/lint/python/pylint.mk
 
 $(if $(DEBUG),$(warning LEAVE))
 
-endif # mk-include--onf-lint-license
-
 # [EOF]
diff --git a/makefiles/lint/python/pylint.mk b/makefiles/lint/python/pylint.mk
index 028f5dc..cf7e173 100644
--- a/makefiles/lint/python/pylint.mk
+++ b/makefiles/lint/python/pylint.mk
@@ -2,7 +2,7 @@
 # -----------------------------------------------------------------------
 # Copyright 2022-2024 Open Networking Foundation (ONF) and the ONF Contributors
 #
-# Licensed under the Apache License, Version 2.0 (the "License");
+# Licensed 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
 #
@@ -15,40 +15,81 @@
 # limitations under the License.
 # -----------------------------------------------------------------------
 
+$(if $(DEBUG),$(warning ENTER))
+
 ##-------------------##
 ##---]  GLOBALS  [---##
 ##-------------------##
+.PHONY: lint-pylint lint-pylint-all lint-pylint-modified
 
-# Gather sources to check
-# TODO: implement deps, only check modified files
-python-check-find := find . -name '*venv*' -prune\
-  -o \( -name '*.py' \)\
-  -type f -print0
-
-# python-check    := $(env-clean) pylint
-python-check    := pylint
-
-# python-check-args += --dry-run
-
-##-------------------##
-##---]  TARGETS  [---##
-##-------------------##
-ifndef NO-LINT-PYTHON
-  lint        : lint-python-pylint
-  lint-python : lint-python-pylint
-endif
+PYTHON_FILES      ?= $(error PYTHON_FILES= required)
 
 ## -----------------------------------------------------------------------
-## Intent: Perform a lint check on makefile sources
+## Intent: Use the pylint command to perform syntax checking.
+##   o If UNSTABLE=1 syntax check all sources
+##   o else only check sources modified by the developer.
+## Usage:
+##   % make lint UNSTABLE=1
+##   % make lint-pylint-all
 ## -----------------------------------------------------------------------
-lint-python-pylint:
-	$(HIDE)$(env-clean) $(python-check-find) \
-	    | $(xargs-n1) $(python-check) $(python-check-args)
+ifndef NO-LINT-PYLINT
+  lint-pylint-mode := $(if $(have-python-files),modified,all)
+  lint        : lint-pylint
+  lint-pylint : lint-pylint-$(lint-pylint-mode)
+endif# NO-LINT-PYLINT
 
 ## -----------------------------------------------------------------------
-## Intent: Display command help
+## Intent: exhaustive pylint syntax checking
 ## -----------------------------------------------------------------------
-help-summary ::
-	@echo '  lint-python-pylint  Syntax check python sources (*.py)'
+
+# Construct: find . \( -name '__ignored__' -o -name dir -o name dir \)
+# pylint-find-filter := $(null)
+# pylint-find-filter += -name '__ignored__'#   # for alignment
+# pylint-find-filter += $(foreach dir,$(onf-excl-dirs),-o -name $(dir)))
+
+# pylint-find-filter := $(call gen-python-find-excl,onf-excl-dirs)
+# $(error pylint-find-filter := $(pylint-find-filter))
+lint-pylint-all: $(venv-activate-script)
+	$(MAKE) --no-print-directory lint-pylint-install
+
+	$(activate) && $(call gen-python-find-cmd) | $(xargs-n1) pylint
+#	    | $(xargs-n1-clean) yamllint --strict
+
+## -----------------------------------------------------------------------
+## Intent: check deps for format and python3 cleanliness
+## Note:
+##   pylint --py3k option no longer supported
+## -----------------------------------------------------------------------
+lint-pylint-modified: $(venv-activate-script)
+	$(MAKE) --no-print-directory lint-pylint-install
+
+	$(activate) && pylint $(PYTHON_FILES)
+
+## -----------------------------------------------------------------------
+## Intent:
+## -----------------------------------------------------------------------
+.PHONY: lint-pylint-install
+lint-pylint-install: $(venv-activate-script)
+	@echo
+	@echo "** -----------------------------------------------------------------------"
+	@echo "** python pylint syntax checking"
+	@echo "** -----------------------------------------------------------------------"
+	$(activate) && pip install --upgrade pylint
+	$(activate) && pylint --version
+	@echo
+
+## -----------------------------------------------------------------------
+## Intent: Display command usage
+## -----------------------------------------------------------------------
+help::
+	@echo '  lint-pylint          Syntax check python using the pylint command'
+  ifdef VERBOSE
+	@echo '  $(MAKE) lint-pylint PYTHON_FILES=...'
+	@echo '  lint-pylint-modified  pylint checking: only modified'
+	@echo '  lint-pylint-all       pylint checking: exhaustive'
+	@echo '  lint-pylint-install   Install the pylint command'
+  endif
+
+$(if $(DEBUG),$(warning LEAVE))
 
 # [EOF]
diff --git a/makefiles/lint/robot/include.mk b/makefiles/lint/robot/include.mk
new file mode 100644
index 0000000..283c729
--- /dev/null
+++ b/makefiles/lint/robot/include.mk
@@ -0,0 +1,65 @@
+# -*- makefile -*-
+# -----------------------------------------------------------------------
+# Copyright 2017-2022 Open Networking Foundation
+#
+# Licensed 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.
+# -----------------------------------------------------------------------
+
+##-------------------##
+##---]  GLOBALS  [---##
+##-------------------##
+.PHONY: lint-robot lint-robot-all lint-robot-modified
+
+have-robot-files := $(if $(strip $(ROBOT_FILES)),true)
+ROBOT_FILES ?= $(error ROBOT_FILES= is required)
+
+## -----------------------------------------------------------------------
+## -----------------------------------------------------------------------
+ifndef NO-LINT-ROBOT
+  lint-robot-mode := $(if $(have-robot-files),modified,all)
+  lint : lint-robot-$(lint-robot-mode)
+endif# NO-LINT-ROBOT
+
+# Consistent targets across lint makefiles
+lint-robot-all      : lint-robot
+lint-robot-modified : lint-robot
+
+LINT_ARGS ?= --verbose --configure LineTooLong:130 -e LineTooLong \
+             --configure TooManyTestSteps:65 -e TooManyTestSteps \
+             --configure TooManyTestCases:50 -e TooManyTestCases \
+             --configure TooFewTestSteps:1 \
+             --configure TooFewKeywordSteps:1 \
+             --configure FileTooLong:2000 -e FileTooLong \
+             -e TrailingWhitespace
+
+## -----------------------------------------------------------------------
+## -----------------------------------------------------------------------
+lint-robot: $(venv-activate-script)
+	@echo
+	@echo '** -----------------------------------------------------------------------'
+	@echo '** robot *.rst syntax checking'
+	@echo '** -----------------------------------------------------------------------'
+#	$(activate) && rflint --version
+	$(activate) && rflint $(LINT_ARGS) $(ROBOT_FILES)
+
+## -----------------------------------------------------------------------
+## Intent: Display command usage
+## -----------------------------------------------------------------------
+help::
+	@echo '  lint-robot          Syntax check python using the robot command'
+  ifdef VERBOSE
+	@echo '  lint-robot-all       robot checking: exhaustive'
+	@echo '  lint-robot-modified  robot checking: only modified'
+  endif
+
+# [EOF]
diff --git a/makefiles/lint/shell.mk b/makefiles/lint/shell.mk
new file mode 100644
index 0000000..3c33bb2
--- /dev/null
+++ b/makefiles/lint/shell.mk
@@ -0,0 +1,65 @@
+# -*- makefile -*-
+# -----------------------------------------------------------------------
+# Copyright 2022-2023 Open Networking Foundation (ONF) and the ONF Contributors
+#
+# Licensed 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.
+# -----------------------------------------------------------------------
+# https://gerrit.opencord.org/plugins/gitiles/onf-make
+# ONF.makefile.version = 1.0
+# -----------------------------------------------------------------------
+
+##-------------------##
+##---]  GLOBALS  [---##
+##-------------------##
+
+# Gather sources to check
+# TODO: implement deps, only check modified files
+shell-check-find := find .
+# vendor scripts but they really should be lintable
+shell-check-find += -name 'vendor' -prune
+shell-check-find += -o \( -name '*.sh' \)
+shell-check-find += -type f -print0
+
+shell-check    := $(env-clean) shellcheck
+# shell-check      := shellcheck
+
+shell-check-args += --check-sourced
+shell-check-args += --external-sources
+
+##-------------------##
+##---]  TARGETS  [---##
+##-------------------##
+ifndef NO-LINT-SHELL
+  lint : lint-shell
+endif
+
+## -----------------------------------------------------------------------
+## Intent: Perform a lint check on command line script sources
+## -----------------------------------------------------------------------
+lint-shell:
+	$(shell-check) -V
+	@echo
+	$(HIDE)$(env-clean) $(shell-check-find) \
+	    | $(xargs-n1) $(shell-check) $(shell-check-args)
+
+## -----------------------------------------------------------------------
+## Intent: Display command help
+## -----------------------------------------------------------------------
+help-summary ::
+	@echo '  lint-shell          Syntax check shell sources'
+
+# [SEE ALSO]
+# -----------------------------------------------------------------------
+#   o https://www.shellcheck.net/wiki/Directive
+
+# [EOF]
diff --git a/makefiles/lint/shellcheck/urls b/makefiles/lint/shellcheck/urls
new file mode 100644
index 0000000..a35dbab
--- /dev/null
+++ b/makefiles/lint/shellcheck/urls
@@ -0,0 +1,5 @@
+# -*- makefile -*-
+
+https://github.com/koalaman/shellcheck/releases/tag/v0.9.0
+
+# [EOF]
\ No newline at end of file
diff --git a/makefiles/lint/yaml./.yamllint b/makefiles/lint/yaml./.yamllint
new file mode 100644
index 0000000..c42c6d5
--- /dev/null
+++ b/makefiles/lint/yaml./.yamllint
@@ -0,0 +1,45 @@
+# -*- makefile -*-
+# -----------------------------------------------------------------------
+# Copyright 2022-2023 Open Networking Foundation (ONF) and the ONF Contributors
+#
+# Licensed 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.
+#
+# SPDX-FileCopyrightText: 2022 Open Networking Foundation (ONF) and the ONF Contributors
+# SPDX-License-Identifier: Apache-2.0
+# -----------------------------------------------------------------------
+---
+
+yaml-files:
+  - '*.yaml'
+  - '*.yml'
+  - '.yamllint'
+
+rules:
+  document-start: disable
+  line-length:
+    max: 160
+
+# -----------------------------------------------------------------------
+# .. seealso: https://gerrit.opencord.org/plugins/gitiles/helm-repo-tools/+/refs/heads/master/yamllint.conf
+# -----------------------------------------------------------------------
+#
+# extends: default
+#
+#rules:
+#  empty-lines:
+#    max-end: 1
+#  line-length:
+#    max: 120
+#  braces:
+#    min-spaces-inside: 0
+#    max-spaces-inside: 1
diff --git a/makefiles/help.mk b/makefiles/lint/yaml./byrepo/voltha-lib-go/include.mk
similarity index 71%
copy from makefiles/help.mk
copy to makefiles/lint/yaml./byrepo/voltha-lib-go/include.mk
index c272d96..6cbd0ea 100644
--- a/makefiles/help.mk
+++ b/makefiles/lint/yaml./byrepo/voltha-lib-go/include.mk
@@ -1,6 +1,6 @@
 # -*- makefile -*-
 # -----------------------------------------------------------------------
-# Copyright 2017-2024 Open Networking Foundation (ONF) and the ONF Contributors
+# Copyright 2023 Open Networking Foundation (ONF) and the ONF Contributors
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -15,9 +15,13 @@
 # limitations under the License.
 # -----------------------------------------------------------------------
 
-# Parent makefile should include this early so help
-# message will be prefixed by a usage statement.
-help ::
-	@echo "Usage: $(MAKE) [options] [target] ..."
+$(if $(DEBUG),$(warning ENTER))
+
+##--------------------##
+##---]  INCLUDES  [---##
+##--------------------##
+include $(ONF_MAKEDIR)/lint/yaml/byrepo/$(--repo-name--)/yamllint.mk
+
+$(if $(DEBUG),$(warning LEAVE))
 
 # [EOF]
diff --git a/makefiles/lint/yaml./byrepo/voltha-lib-go/python.mk b/makefiles/lint/yaml./byrepo/voltha-lib-go/python.mk
new file mode 100644
index 0000000..cf0eef5
--- /dev/null
+++ b/makefiles/lint/yaml./byrepo/voltha-lib-go/python.mk
@@ -0,0 +1,41 @@
+# -*- makefile -*-
+# -----------------------------------------------------------------------
+# Copyright 2022-2023 Open Networking Foundation (ONF) and the ONF Contributors
+#
+# Licensed 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.
+#
+# SPDX-FileCopyrightText: 2022 Open Networking Foundation (ONF) and the ONF Contributors
+# SPDX-License-Identifier: Apache-2.0
+# -----------------------------------------------------------------------
+
+YAML_FILES ?= $(error YAML_FILES= is required)
+
+lint-yaml-dep = $(addsuffix ^lint-yaml,$(YAML_FILES))
+lint-yaml-src = $(firstword $(subst ^,$(space),$(1)))
+
+##-------------------##
+##---]  TARGETS  [---##
+##-------------------##
+.PHONY : lint-yaml
+lint   : lint-yaml
+
+lint-yaml: $(venv-activate)
+lint-yaml: $(lint-yaml-dep)
+
+$(lint-yaml-dep):
+	$(vst-env) && yamllint -s $(call lint-yaml-src,$@)
+
+help::
+	@echo "  lint-yaml            Syntax check yaml sources"
+
+# [EOF]
diff --git a/makefiles/lint/yaml./byrepo/voltha-lib-go/repo b/makefiles/lint/yaml./byrepo/voltha-lib-go/repo
new file mode 100644
index 0000000..99e8451
--- /dev/null
+++ b/makefiles/lint/yaml./byrepo/voltha-lib-go/repo
@@ -0,0 +1 @@
+Source from voltha-lib-go
\ No newline at end of file
diff --git a/makefiles/lint/yaml./byrepo/voltha-lib-go/todo b/makefiles/lint/yaml./byrepo/voltha-lib-go/todo
new file mode 100644
index 0000000..8400c64
--- /dev/null
+++ b/makefiles/lint/yaml./byrepo/voltha-lib-go/todo
@@ -0,0 +1,39 @@
+# -*- makefile -*-
+# -----------------------------------------------------------------------
+# Copyright 2022-2023 Open Networking Foundation (ONF) and the ONF Contributors
+# -----------------------------------------------------------------------
+
+##-------------------##
+##---]  GLOBALS  [---##
+##-------------------##
+env-clean = /usr/bin/env --ignore-environment
+xargs-n1      := xargs -0 -t -n1 --no-run-if-empty
+
+yamllint      := $(env-clean) $(YAMLLINT)
+yamllint-args := -c .yamllint
+
+##-------------------##
+##---]  TARGETS  [---##
+##-------------------##
+lint : lint-yaml
+
+## -----------------------------------------------------------------------
+## -----------------------------------------------------------------------
+lint-yaml:
+	$(HIDE)$(env-clean) find . -name '*.yaml' -type f -print0 \
+	    | $(xargs-n1) $(yamllint) $(yamllint-args)
+
+## -----------------------------------------------------------------------
+## -----------------------------------------------------------------------
+help:
+	@echo
+	@echo "USAGE: $(MAKE)"
+	@echo "  lint        perform syntax checks on source"
+	@echo "  test        perform syntax checks on source"
+	@echo "  pre-check   Verify tools and deps are available for testing"
+	@echo
+	@echo "[LINT]"
+	@echo "  lint-json   Syntax check .json sources"
+	@echo "  lint-yaml   Syntax check .yaml sources"
+	@echo
+# [EOF]
diff --git a/makefiles/lint/yaml./byrepo/voltha-lib-go/urls b/makefiles/lint/yaml./byrepo/voltha-lib-go/urls
new file mode 100644
index 0000000..8747658
--- /dev/null
+++ b/makefiles/lint/yaml./byrepo/voltha-lib-go/urls
@@ -0,0 +1,5 @@
+# -*- makefile -*-
+
+https://yamllint.readthedocs.io/en/stable/configuration.html
+
+# [EOF]
\ No newline at end of file
diff --git a/makefiles/help.mk b/makefiles/lint/yaml./byrepo/voltha-lib-go/yamllint.helm
similarity index 66%
copy from makefiles/help.mk
copy to makefiles/lint/yaml./byrepo/voltha-lib-go/yamllint.helm
index c272d96..bf1d2b9 100644
--- a/makefiles/help.mk
+++ b/makefiles/lint/yaml./byrepo/voltha-lib-go/yamllint.helm
@@ -1,6 +1,6 @@
 # -*- makefile -*-
 # -----------------------------------------------------------------------
-# Copyright 2017-2024 Open Networking Foundation (ONF) and the ONF Contributors
+# Copyright 2022-2023 Open Networking Foundation (ONF) and the ONF Contributors
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -13,11 +13,20 @@
 # 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.
+#
+# SPDX-FileCopyrightText: 2022 Open Networking Foundation (ONF) and the ONF Contributors
+# SPDX-License-Identifier: Apache-2.0
 # -----------------------------------------------------------------------
+---
+# yamllint.conf
 
-# Parent makefile should include this early so help
-# message will be prefixed by a usage statement.
-help ::
-	@echo "Usage: $(MAKE) [options] [target] ..."
+extends: default
 
-# [EOF]
+rules:
+  empty-lines:
+    max-end: 1
+  line-length:
+    max: 120
+  braces:
+    min-spaces-inside: 0
+    max-spaces-inside: 1
diff --git a/makefiles/lint/yaml./byrepo/voltha-lib-go/yamllint.mk b/makefiles/lint/yaml./byrepo/voltha-lib-go/yamllint.mk
new file mode 100644
index 0000000..fb56e3a
--- /dev/null
+++ b/makefiles/lint/yaml./byrepo/voltha-lib-go/yamllint.mk
@@ -0,0 +1,72 @@
+# -*- makefile -*-
+# -----------------------------------------------------------------------
+# Copyright 2022-2023 Open Networking Foundation (ONF) and the ONF Contributors
+#
+# Licensed 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.
+#
+# SPDX-FileCopyrightText: 2022 Open Networking Foundation (ONF) and the ONF Contributors
+# SPDX-License-Identifier: Apache-2.0
+# -----------------------------------------------------------------------
+
+$(if $(DEBUG),$(warning ENTER))
+
+--onf-mk-lint-yaml-- := true#       # Inhibit loading downstream lint-yaml targets
+
+# yamllint      := $(env-clean) yamllint
+# yamllint      := $(activate) && yamllint
+
+YAMLLINT = $(activate) && yamllint
+
+## -------------------------------
+## Add requirement(s) for checking
+## -------------------------------
+yamllint-cfg  := yamllint.helm
+yamllint-conf = $(wildcard $(yamllint-cfg) $(ONF_MAKEDIR)/lint/yaml/$(yamllint-cfg))
+yamllint-args += $(addprefix --config-file$(space),$(yamllint-conf))
+yamllint-args += --strict
+
+## -----------------------------------------------------------------------
+## Intent: Use the yaml command to perform syntax checking.
+## -----------------------------------------------------------------------
+ifndef NO-LINT-YAML
+  # lint-yaml-mode := $(if $(have-yaml-files),modified,all)
+  lint      : lint-yaml
+  lint-yaml : lint-yaml-votlha-lib-go
+#  lint-yaml : lint-yaml-all-votlha-lib-go-$(lint-yaml-mode)
+endif# NO-LINT-YAML
+
+## -----------------------------------------------------------------------
+## ----------------------------------------------------------------------
+lint-yaml-votlha-lib-go: lint-yaml-cmd-version
+
+	$(call banner-enter,Target $@)
+	$(HIDE)$(MAKE) --no-print-directory lint-yaml-install
+
+	$(HIDE)$(env-clean) $(call gen-yaml-find-cmd) \
+	    | $(env-clean) $(xargs-cmd) -I'{}' \
+		bash -c "$(YAMLLINT) $(yamllint-args) {}"
+	$(call banner-leave,Target $@)
+
+## -----------------------------------------------------------------------
+## Intent: Display command usage
+## -----------------------------------------------------------------------
+help::
+  # lint-yaml help already displayed by lint/yaml/help.mk
+  ifdef VERBOSE
+	@echo '  $(MAKE) lint-yaml YAML_FILES=...'
+	@echo '  lint-yaml-votlha-lib-go   lint-yaml for repo:voltha-lib-go'
+  endif
+
+$(if $(DEBUG),$(warning LEAVE))
+
+# [EOF]
diff --git a/makefiles/lint/yaml./find_utils.mk b/makefiles/lint/yaml./find_utils.mk
new file mode 100644
index 0000000..49d4cb0
--- /dev/null
+++ b/makefiles/lint/yaml./find_utils.mk
@@ -0,0 +1,32 @@
+# -*- makefile -*-
+# -----------------------------------------------------------------------
+# Intent:
+#   o Construct a find command able to gather python files with filtering.
+#   o Used by library makefiles flake8.mk and pylint.mk for iteration.
+# -----------------------------------------------------------------------
+
+## -----------------------------------------------------------------------
+## Intent: Construct a string for invoking find \( excl-pattern \) -prune
+# -----------------------------------------------------------------------
+gen-yaml-find-excl = \
+  $(strip \
+	-name '__ignored__' \
+	$(foreach dir,$($(1)),-o -name $(dir)) \
+  )
+
+## -----------------------------------------------------------------------
+## Intent: Construct a find command to gather a list of python files
+##         with exclusions.
+## -----------------------------------------------------------------------
+## Usage:
+#	$(activate) & $(call gen-python-find-cmd) | $(args-n1) pylint
+## -----------------------------------------------------------------------
+gen-yaml-find-cmd = \
+  $(strip \
+    find . \
+      \( $(call gen-yaml-find-excl,onf-excl-dirs) \) -prune \
+      -o \( -iname '*.yaml' -o -iname '*.yml' \) \
+      -print0 \
+  )
+
+# [EOF]
diff --git a/makefiles/lint/yaml./help.mk b/makefiles/lint/yaml./help.mk
new file mode 100644
index 0000000..ef8621e
--- /dev/null
+++ b/makefiles/lint/yaml./help.mk
@@ -0,0 +1,41 @@
+# -*- makefile -*-
+# -----------------------------------------------------------------------
+# Copyright 2017-2023 Open Networking Foundation (ONF) and the ONF Contributors
+#
+# Licensed 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.
+# -----------------------------------------------------------------------
+
+$(if $(DEBUG),$(warning ENTER))
+
+## ---------------------------------------------------------------------------
+## Intent: Display a help banner early so includes below that also define
+##         help targets will be displayed beneath a high level banner.
+## ---------------------------------------------------------------------------
+help ::
+  ifndef VERBOSE
+	@echo '  lint-yaml          Invoke all yaml linting targets'
+  else
+	$(HIDE)$(MAKE) --no-print-directory help-lint-yaml
+  endif
+
+## ---------------------------------------------------------------------------
+## Intent: Display extended target help
+## ---------------------------------------------------------------------------
+help-lint-yaml:
+	@echo
+	@echo '[LINT: yaml]   (make lint-yaml VERBOSE=1)'
+	@echo '  lint-yaml          Invoke all yaml linting targets'
+
+$(if $(DEBUG),$(warning LEAVE))
+
+# [EOF]
diff --git a/makefiles/lint/yaml./include.mk b/makefiles/lint/yaml./include.mk
new file mode 100644
index 0000000..26c4a7f
--- /dev/null
+++ b/makefiles/lint/yaml./include.mk
@@ -0,0 +1,42 @@
+# -*- makefile -*-
+# -----------------------------------------------------------------------
+# Copyright 2017-2023 Open Networking Foundation (ONF) and the ONF Contributors
+#
+# Licensed 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.
+# -----------------------------------------------------------------------
+
+ifndef --onf-mk-lint-yaml--
+
+$(if $(DEBUG),$(warning ENTER))
+
+##--------------------##
+##---]  INCLUDES  [---##
+##--------------------##
+include $(ONF_MAKEDIR)/lint/yaml/help.mk
+include $(ONF_MAKEDIR)/lint/yaml/find_utils.mk
+include $(ONF_MAKEDIR)/lint/yaml/install.mk
+
+# [TODO] Consolidate and refactor to support a simpler answer
+# Special snowflake linting requirements
+-include $(ONF_MAKEDIR)/lint/yaml/byrepo/$(--repo-name--)/include.mk
+
+# Standard lint-yaml targets
+include $(ONF_MAKEDIR)/lint/yaml/yamllint.mk
+
+--onf-mk-lint-yaml-- := true#        # Flag to inhibit re-including
+
+$(if $(DEBUG),$(warning LEAVE))
+
+endif # --onf-mk-lint-yaml--
+
+# [EOF]
diff --git a/makefiles/lint/yaml./install.mk b/makefiles/lint/yaml./install.mk
new file mode 100644
index 0000000..a17c3b7
--- /dev/null
+++ b/makefiles/lint/yaml./install.mk
@@ -0,0 +1,69 @@
+# -*- makefile -*-
+# -----------------------------------------------------------------------
+# Copyright 2022-2023 Open Networking Foundation (ONF) and the ONF Contributors
+#
+# Licensed 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.
+#
+# SPDX-FileCopyrightText: 2022 Open Networking Foundation (ONF) and the ONF Contributors
+# SPDX-License-Identifier: Apache-2.0
+# -----------------------------------------------------------------------
+
+$(if $(DEBUG),$(warning ENTER))
+
+## -----------------------------------------------------------------------
+## Intent: Install the yamllint tool
+## -----------------------------------------------------------------------
+.PHONY: lint-yaml-install
+
+# -----------------------------------------------------------------------
+# We can(/should?) define a command macro
+# wait a bit until use cases are better known.
+# Initial use required inserting xargs bash -c "$(YAMLLINT) {}"
+# -----------------------------------------------------------------------
+# YAMLLINT ?= $(venv-activate-bin)/yamllint
+# YAMLLINT ?= $(activate) && yamllint
+
+## -----------------------------------------------------------------------
+## Intent: Display yamllint command version string.
+##   Note: As a side effect, install yamllint by dependency
+## -----------------------------------------------------------------------
+.PHONY: lint-yaml-cmd-version
+lint-yaml-cmd-version : $(venv-activate-bin)/yamllint
+
+	$(HIDE) echo
+	$< --version
+
+## -----------------------------------------------------------------------
+## Intent: On-demand instalation of the yamllint command
+## -----------------------------------------------------------------------
+lint-yaml-install := $(venv-activate-bin)/yamllint
+$(lint-yaml-install) : $(venv-activate-script)
+
+	$(call banner-enter,Target $@)
+	$(activate) && pip install yamllint
+	$(call banner-leave,Target $@)
+
+## -----------------------------------------------------------------------
+## Intent: Purge yamllint tool installation
+## -----------------------------------------------------------------------
+sterile ::
+	$(HIDE)$(RM) "$(venv-abs-bin)/yamllint"
+	$(HIDE)$(RM) -r .venv/lib/*/site-packages/yamllint
+
+## -----------------------------------------------------------------------
+## Intent: Display command usage
+## -----------------------------------------------------------------------
+help::
+	@echo '  lint-yaml-install       Install the yamllint tool'
+
+# [EOF]
diff --git a/makefiles/lint/yaml./yamllint.mk b/makefiles/lint/yaml./yamllint.mk
new file mode 100644
index 0000000..1563c7c
--- /dev/null
+++ b/makefiles/lint/yaml./yamllint.mk
@@ -0,0 +1,78 @@
+# -*- makefile -*-
+# -----------------------------------------------------------------------
+# Copyright 2017-2023 Open Networking Foundation (ONF) and the ONF Contributors
+#
+# Licensed 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.
+# -----------------------------------------------------------------------
+
+$(if $(DEBUG),$(warning ENTER))
+
+##-------------------##
+##---]  GLOBALS  [---##
+##-------------------##
+.PHONY: lint-yaml lint-yaml-all lint-yaml-modified
+
+have-yaml-files := $(if $(strip $(YAML_FILES)),true)
+YAML_FILES      ?= $(error YAML_FILES= is required)
+
+YAMLLINT = $(activate) && yamllint
+yamllint-args += --strict
+
+## -----------------------------------------------------------------------
+## Intent: Use the yaml command to perform syntax checking.
+## -----------------------------------------------------------------------
+ifndef NO-LINT-YAML
+  lint-yaml-mode := $(if $(have-yaml-files),modified,all)
+  lint      : lint-yaml
+  lint-yaml : lint-yaml-$(lint-yaml-mode)
+endif# NO-LINT-YAML
+
+## -----------------------------------------------------------------------
+## Intent: exhaustive yaml syntax checking
+## -----------------------------------------------------------------------
+lint-yaml-all: lint-yaml-cmd-version
+
+	$(call banner-enter,Target $@)
+	$(HIDE)$(MAKE) --no-print-directory lint-yaml-install
+	$(HIDE)$(activate) && $(call gen-yaml-find-cmd) \
+	    | $(env-clean) $(xargs-cmd) -I'{}' \
+		bash -c "$(YAMLLINT) $(yamllint-args) {}"
+	$(call banner-leave,Target $@)
+
+## -----------------------------------------------------------------------
+## Intent: check deps for format and python3 cleanliness
+## Note:
+##   yaml --py3k option no longer supported
+## -----------------------------------------------------------------------
+lint-yaml-modified: lint-yaml-cmd-version
+
+	$(call banner-enter,Target $@)
+	$(HIDE)$(MAKE) --no-print-directory lint-yaml-install
+	$(YAMLLINT) $(yamllint-args) $(YAML_FILES)
+	$(call banner-leave,Target $@)
+
+## -----------------------------------------------------------------------
+## Intent: Display command usage
+## -----------------------------------------------------------------------
+help::
+	@echo '  lint-yaml          Syntax check python using the yaml command'
+  ifdef VERBOSE
+	@echo '  $(MAKE) lint-yaml YAML_FILES=...'
+	@echo '  lint-yaml-all       yaml checking: exhaustive'
+	@echo '  lint-yaml-modified  yaml checking: only locally modified'
+	@echo '  lint-yaml-install   Install the pylint command'
+  endif
+
+$(if $(DEBUG),$(warning LEAVE))
+
+# [EOF]
diff --git a/makefiles/lint/yaml.mk b/makefiles/lint/yaml.mk
new file mode 100644
index 0000000..ab5b9d6
--- /dev/null
+++ b/makefiles/lint/yaml.mk
@@ -0,0 +1,84 @@
+# -*- makefile -*-
+# -----------------------------------------------------------------------
+# Copyright 2017-2023 Open Networking Foundation (ONF) and the ONF Contributors
+#
+# Licensed 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.
+# -----------------------------------------------------------------------
+
+$(if $(DEBUG),$(warning ENTER))
+
+##-------------------##
+##---]  GLOBALS  [---##
+##-------------------##
+.PHONY: lint-yaml lint-yaml-all lint-yaml-modified
+
+have-yaml-files := $(if $(strip $(YAML_FILES)),true)
+YAML_FILES      ?= $(error YAML_FILES= is required)
+
+## -----------------------------------------------------------------------
+## Intent: Use the yaml command to perform syntax checking.
+##   o If UNSTABLE=1 syntax check all sources
+##   o else only check sources modified by the developer.
+## Usage:
+##   % make lint UNSTABLE=1
+##   % make lint-yaml-all
+## -----------------------------------------------------------------------
+lint-yaml-mode := $(if $(have-yaml-files),modified,all)
+lint-yaml : lint-yaml-$(lint-yaml-mode)
+
+ifndef NO-LINT-YAML
+  lint : lint-yaml#     # Enable as a default lint target
+endif# NO-LINT-YAML
+
+## -----------------------------------------------------------------------
+## Intent: exhaustive yaml syntax checking
+## -----------------------------------------------------------------------
+lint-yaml-all:
+	$(HIDE)$(MAKE) --no-print-directory lint-yaml-install
+
+	find . \( -iname '*.yaml' -o -iname '*.yml' \) -print0 \
+	    | $(xargs-n1-clean) yamllint --strict
+
+## -----------------------------------------------------------------------
+## Intent: check deps for format and python3 cleanliness
+## Note:
+##   yaml --py3k option no longer supported
+## -----------------------------------------------------------------------
+lint-yaml-modified:
+	$(HIDE)$(MAKE) --no-print-directory lint-yaml-install
+	yamllint -s $(YAML_FILES)
+
+## -----------------------------------------------------------------------
+## Intent:
+## -----------------------------------------------------------------------
+lint-yaml-install:
+	@echo
+	@echo "** -----------------------------------------------------------------------"
+	@echo "** yaml syntax checking"
+	@echo "** -----------------------------------------------------------------------"
+	yamllint --version
+	@echo
+
+## -----------------------------------------------------------------------
+## Intent: Display command usage
+## -----------------------------------------------------------------------
+help::
+	@echo '  lint-yaml          Syntax check python using the yaml command'
+  ifdef VERBOSE
+	@echo '  lint-yaml-all       yaml checking: exhaustive'
+	@echo '  lint-yaml-modified  yaml checking: only locally modified'
+  endif
+
+$(if $(DEBUG),$(warning LEAVE))
+
+# [EOF]
diff --git a/makefiles/lint/yaml/install.mk b/makefiles/lint/yaml/install.mk
index edcc212..19e8628 100644
--- a/makefiles/lint/yaml/install.mk
+++ b/makefiles/lint/yaml/install.mk
@@ -60,6 +60,10 @@
 	$(HIDE)$(RM) "$(venv-abs-bin)/yamllint"
 	$(HIDE)$(RM) -r .venv/lib/*/site-packages/yamllint
 
+        # Remove both file:command and dir:libraries
+        # find "$(venv-abs-path)" -iname 'yamllint' -print0 \
+        #    | $(xargs-n1-clean) $(RM) -r {}
+
 ## -----------------------------------------------------------------------
 ## Intent: Display command usage
 ## -----------------------------------------------------------------------
diff --git a/makefiles/targets/include.mk b/makefiles/targets/include.mk
new file mode 100644
index 0000000..20e1bf5
--- /dev/null
+++ b/makefiles/targets/include.mk
@@ -0,0 +1,36 @@
+# -*- makefile -*-
+# -----------------------------------------------------------------------
+# Copyright 2022-2023 Open Networking Foundation (ONF) and the ONF Contributors
+#
+# Licensed 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.
+#
+# SPDX-FileCopyrightText: 2022-2023 Open Networking Foundation (ONF) and the ONF Contributors
+# SPDX-License-Identifier: Apache-2.0
+# -----------------------------------------------------------------------
+# https://gerrit.opencord.org/plugins/gitiles/onf-make
+# ONF.makefile.version = 1.0
+# -----------------------------------------------------------------------
+
+$(if $(DEBUG),$(warning ENTER))
+
+##-------------------##
+##---]  TARGETS  [---##
+##-------------------##
+include $(ONF_MAKEDIR)/targets/clean.mk
+include $(ONF_MAKEDIR)/targets/check.mk
+include $(ONF_MAKEDIR)/targets/sterile.mk
+include $(ONF_MAKEDIR)/targets/test/include.mk
+
+$(if $(DEBUG),$(warning LEAVE))
+
+# [EOF]
diff --git a/makefiles/todo.mk b/makefiles/todo.mk
index 39c7044..e9cdc94 100644
--- a/makefiles/todo.mk
+++ b/makefiles/todo.mk
@@ -22,7 +22,8 @@
 
 todo ::
 	@echo '[TODO]'
-	@echo '  o volthaStackDeploy.groovy - post v2.11 release cleanup for 2.8'
+	@echo '  o item 1'
+	@echo '  o item 2'
 
 ## -----------------------------------------------------------------------
 ## -----------------------------------------------------------------------
diff --git a/makefiles/help.mk b/makefiles/urls
similarity index 83%
rename from makefiles/help.mk
rename to makefiles/urls
index c272d96..8c08fb6 100644
--- a/makefiles/help.mk
+++ b/makefiles/urls
@@ -15,9 +15,7 @@
 # limitations under the License.
 # -----------------------------------------------------------------------
 
-# Parent makefile should include this early so help
-# message will be prefixed by a usage statement.
-help ::
-	@echo "Usage: $(MAKE) [options] [target] ..."
+## Common library makefiles
+https://github.com/opencord/onf-make
 
 # [EOF]
diff --git a/patches/README.md b/patches/README.md
index a72d09a..f3302b9 100644
--- a/patches/README.md
+++ b/patches/README.md
@@ -20,7 +20,7 @@
     python < 3.10   (collections.abc optional)
 
 
-# vst_venv/
+# .venv/
 
 Makefile will first create a python virtualenv directory to selectively
 use packages.  After setup patches are applied to venv (as a transition)
@@ -29,15 +29,15 @@
 
 # staging/
 
-The staging directory is used for comparison with the vst_venv directory
+The staging directory is used for comparison with the .venv directory
 to generate patches.  Populate the directory with a copy of a cleanly
 patched virtual interpreter then modify files benath/ staging to generate
 a patch from.
 
 % make sterile
-% make vst_venv
+% make .venv
 % mkdir staging
-% rsync -rv --checksum vst_venv/. staging/.
+% rsync -rv --checksum .venv/. staging/.
 [NOTE] Make python 3.10+ migration edits beneath staging as needed
 % make patch-gather
 % make sterile
diff --git a/patches/lib/python3.10/site-packages/robot/utils/normalizing.py/patch b/patches/lib/python3.10/site-packages/robot/utils/normalizing.py/patch
index fc9ddd4..ae8619a 100644
--- a/patches/lib/python3.10/site-packages/robot/utils/normalizing.py/patch
+++ b/patches/lib/python3.10/site-packages/robot/utils/normalizing.py/patch
@@ -1,5 +1,5 @@
 --- vault/lib/python3.10/site-packages/robot/utils/normalizing.py	2022-11-26 06:59:47.438751606 -0500
-+++ vst_venv/lib/python3.10/site-packages/robot/utils/normalizing.py	2022-11-26 06:57:29.960476182 -0500
++++ .venv/lib/python3.10/site-packages/robot/utils/normalizing.py	2022-11-26 06:57:29.960476182 -0500
 @@ -13,10 +13,7 @@
  #  See the License for the specific language governing permissions and
  #  limitations under the License.
diff --git a/patches/lib/python3.10/site-packages/robot/utils/robottypes3.py/patch b/patches/lib/python3.10/site-packages/robot/utils/robottypes3.py/patch
index 399a769..d1aa540 100644
--- a/patches/lib/python3.10/site-packages/robot/utils/robottypes3.py/patch
+++ b/patches/lib/python3.10/site-packages/robot/utils/robottypes3.py/patch
@@ -1,5 +1,5 @@
 --- vault/lib/python3.10/site-packages/robot/utils/robottypes3.py	2022-11-26 07:00:17.126386733 -0500
-+++ vst_venv/lib/python3.10/site-packages/robot/utils/robottypes3.py	2022-11-26 06:57:29.956476232 -0500
++++ .venv/lib/python3.10/site-packages/robot/utils/robottypes3.py	2022-11-26 06:57:29.956476232 -0500
 @@ -13,12 +13,7 @@
  #  See the License for the specific language governing permissions and
  #  limitations under the License.
diff --git a/patches/python_310_migration.sh b/patches/python_310_migration.sh
index 4b27c3f..b522caa 100755
--- a/patches/python_310_migration.sh
+++ b/patches/python_310_migration.sh
@@ -15,52 +15,71 @@
 # limitations under the License.
 # -----------------------------------------------------------------------
 
+##-------------------##
+##---]  GLOBALS  [---##
+##-------------------##
 set -euo pipefail
 
-dst="vst_venv" # rename to .venv
-src="staging"
-pat="patches"
+## -----------------------------------------------------------------------
+## Intent: Display script documentation.
+## -----------------------------------------------------------------------
+function show_help()
+{
+    cat <<EOH
+Usage: $0
+  apply    Patch virtualenv python modules by version (3.10+).
+  backup   Create a tarball for work-in-progress.
+  gather   Display a list of potential source files to patch.
 
-declare -a fyls=()
-fyls+=('lib/python3.10/site-packages/robot/utils/normalizing.py')
-fyls+=('lib/python3.10/site-packages/robot/utils/robottypes3.py')
+  --venv   Installed venv directory to patch (override default)
+  --help   This message
 
-echo
-echo "==========================================================================="
-echo "CMD: $0"
-echo "PWD: $(/bin/pwd)"
-echo "ARGV: $*"
-echo "==========================================================================="
+See Also
+  patches/README.md       Howto create a patch file.
+
+EOH
+    exit 0
+}
+
+##----------------##
+##---]  MAIN  [---##
+##----------------##
+declare dst='.venv'  # "vst_venv"
+declare src="staging"
+declare pat="patches"
+
+## -----------------------
+## Slurp available patches
+## -----------------------
+pushd "$pat" >/dev/null
+readarray -t fyls < <(find . -name 'patch' -print)
+popd         >/dev/null
 
 if [ $# -eq 0 ]; then set -- apply; fi
 
 while [ $# -gt 0 ]; do
     opt="$1"; shift
     case "$opt" in
-	help)
-	    cat <<EOH
-apply  - generate patches from vault source.
-backup - Archive patch directory
-gather - collect potential python files to edit.
-EOH
-	    ;;
 
-	--venv) dst="$1"; shift ;;
-	
+	-*help) show_help ;;
+	-*venv) dst="$1"; shift ;;
+
 	apply)
-	    pushd "$dst" || { echo "pushd $dst failed"; exit 1; }
+	    pushd "$dst" >/dev/null || { echo "pushd $dst failed"; exit 1; }
 	    for fyl in "${fyls[@]}";
 	    do
+		path="${fyl%/*}"
+
 		# Conditional install, jenkins may not support interpreter yet.
-		if [ ! -e "$fyl" ]; then
-		    echo "[SKIP] No venv file to patch: $fyl"
+		if [ ! -e "$path" ]; then
+		    echo "[SKIP] $path"
 		    continue
 		fi
 		
-		echo "$fyl"
-		patch -R -p1 < "../$pat/$fyl/patch"
+		echo "[APPLY] $path"
+		patch -R -p1 < "../$pat/${path}/patch"
 	    done
-	    popd || { echo "popd $dst failed"; exit 1; }
+	    popd >/dev/null || { echo "popd $dst failed"; exit 1; }
 	    ;;
 
 	backup)
@@ -71,7 +90,6 @@
 	    ;;
 
 	gather)
-	    set -x
 	    for fyl in "${fyls[@]}";
 	    do
 		patchDir="$pat/$fyl"
@@ -79,14 +97,17 @@
 		diff -Naur "$src/$fyl" "$dst/$fyl" | tee "$pat/$fyl/patch"
 	    done
 	    find "$pat" -print
-	    set +x
 	    ;;
-	
+
+	help) show_help ;;
+
 	*)
 	    echo "ERROR: Unknown action [$opt]"
 	    exit 1
 	    ;;
     esac
+
+    echo
 done
 
 # [EOF]