diff --git a/Documentation/Examples/CMakeLists.txt b/Documentation/Examples/CMakeLists.txt
index 131476a3a7c133e7d1b093a05a67ca830494be39..ffc14426f790c8c760d77fdc056d782836bc1a94 100644
--- a/Documentation/Examples/CMakeLists.txt
+++ b/Documentation/Examples/CMakeLists.txt
@@ -31,7 +31,7 @@ target_link_libraries (cascade_example SuperStupidStack CORSIKAunits
   ProcessPythia
   CORSIKAcascade
   ProcessEnergyLoss
-#  ProcessStackInspector
+  ProcessStackInspector
   ProcessTrackWriter
   ProcessTrackingLine
   CORSIKAprocesses
@@ -71,7 +71,6 @@ target_link_libraries (cascade_proton_example SuperStupidStack CORSIKAunits
   ProcessPythia
   CORSIKAcascade
   ProcessEnergyLoss
-#  ProcessStackInspector
   ProcessTrackWriter
   ProcessTrackingLine
   ProcessHadronicElasticModel
@@ -82,6 +81,7 @@ target_link_libraries (cascade_proton_example SuperStupidStack CORSIKAunits
   CORSIKAenvironment
   CORSIKAprocesssequence
   )
+
 install (TARGETS cascade_proton_example DESTINATION share/examples)
 CORSIKA_ADD_TEST (cascade_proton_example)
 
@@ -94,7 +94,6 @@ target_link_libraries (vertical_EAS SuperStupidStack CORSIKAunits
   ProcessPythia
   CORSIKAcascade
   ProcessEnergyLoss
-#  ProcessStackInspector
   ProcessTrackWriter
   ProcessTrackingLine
   ProcessHadronicElasticModel
@@ -106,7 +105,7 @@ target_link_libraries (vertical_EAS SuperStupidStack CORSIKAunits
   CORSIKAprocesssequence
   )
 install (TARGETS vertical_EAS DESTINATION share/examples)
-CORSIKA_ADD_TEST (vertical_EAS)
+# CORSIKA_ADD_TEST (vertical_EAS) not yet...
 
 add_executable (staticsequence_example staticsequence_example.cc)
 target_compile_options(staticsequence_example PRIVATE -g) # do not skip asserts
diff --git a/Documentation/Examples/boundary_example.cc b/Documentation/Examples/boundary_example.cc
index 0c767160e08123292379ad330941c2f37479b627..b1d540eebb540c10063ef79648086f749d779ba9 100644
--- a/Documentation/Examples/boundary_example.cc
+++ b/Documentation/Examples/boundary_example.cc
@@ -51,7 +51,7 @@ using namespace corsika::environment;
 using namespace std;
 using namespace corsika::units::si;
 
-class ProcessCut : public process::ContinuousProcess<ProcessCut> {
+class ProcessCut : public process::SecondariesProcess<ProcessCut> {
 
   HEPEnergyType fECut;
 
@@ -145,47 +145,38 @@ public:
     return is_inv;
   }
 
-  template <typename Particle>
-  LengthType MaxStepLength(Particle& p, setup::Trajectory&) const {
-    cout << "ProcessCut: MinStep: pid: " << p.GetPID() << endl;
-    cout << "ProcessCut: MinStep: energy (GeV): " << p.GetEnergy() / 1_GeV << endl;
-    const Code pid = p.GetPID();
-    if (isEmParticle(pid) || isInvisible(pid) || isBelowEnergyCut(p)) {
-      cout << "ProcessCut: MinStep: next cut: " << 0. << endl;
-      return 0_m;
-    } else {
-      LengthType next_step = 1_m * std::numeric_limits<double>::infinity();
-      cout << "ProcessCut: MinStep: next cut: " << next_step << endl;
-      return next_step;
-    }
-  }
-
-  template <typename Particle, typename Stack>
-  EProcessReturn DoContinuous(Particle& p, setup::Trajectory&, Stack&) {
-    const Code pid = p.GetPID();
-    HEPEnergyType energy = p.GetEnergy();
-    cout << "ProcessCut: DoContinuous: " << pid << " E= " << energy
-         << ", EcutTot=" << (fEmEnergy + fInvEnergy + fEnergy) / 1_GeV << " GeV" << endl;
-    EProcessReturn ret = EProcessReturn::eOk;
-    if (isEmParticle(pid)) {
-      cout << "removing em. particle..." << endl;
-      fEmEnergy += energy;
-      fEmCount += 1;
-      // p.Delete();
-      ret = EProcessReturn::eParticleAbsorbed;
-    } else if (isInvisible(pid)) {
-      cout << "removing inv. particle..." << endl;
-      fInvEnergy += energy;
-      fInvCount += 1;
-      // p.Delete();
-      ret = EProcessReturn::eParticleAbsorbed;
-    } else if (isBelowEnergyCut(p)) {
-      cout << "removing low en. particle..." << endl;
-      fEnergy += energy;
-      // p.Delete();
-      ret = EProcessReturn::eParticleAbsorbed;
+  template <typename TSecondaries>
+  EProcessReturn DoSecondaries(TSecondaries& vS) {
+    auto p = vS.begin();
+    while (p != vS.end()) {
+      const Code pid = p.GetPID();
+      HEPEnergyType energy = p.GetEnergy();
+      cout << "ProcessCut: DoSecondaries: " << pid << " E= " << energy
+           << ", EcutTot=" << (fEmEnergy + fInvEnergy + fEnergy) / 1_GeV << " GeV"
+           << endl;
+      if (isEmParticle(pid)) {
+        cout << "removing em. particle..." << endl;
+        fEmEnergy += energy;
+        fEmCount += 1;
+        p.Delete();
+      } else if (isInvisible(pid)) {
+        cout << "removing inv. particle..." << endl;
+        fInvEnergy += energy;
+        fInvCount += 1;
+        p.Delete();
+      } else if (isBelowEnergyCut(p)) {
+        cout << "removing low en. particle..." << endl;
+        fEnergy += energy;
+        p.Delete();
+      } else if (p.GetTime() > 10_ms) {
+        cout << "removing OLD particle..." << endl;
+        fEnergy += energy;
+        p.Delete();
+      } else {
+        ++p; // next entry in SecondaryView
+      }
     }
-    return ret;
+    return EProcessReturn::eOk;
   }
 
   void Init() {
@@ -251,7 +242,7 @@ int main() {
   random::RNGManager::GetInstance().RegisterRandomStream("cascade");
 
   // setup environment, geometry
-  using EnvType = environment::Environment<setup::IEnvironmentModel>;
+  using EnvType = Environment<setup::IEnvironmentModel>;
   EnvType env;
   auto& universe = *(env.GetUniverse());
 
@@ -282,15 +273,16 @@ int main() {
 
   random::RNGManager::GetInstance().RegisterRandomStream("s_rndm");
   process::sibyll::Interaction sibyll;
-  process::sibyll::NuclearInteraction sibyllNuc(sibyll);
-  process::sibyll::Decay decay;
+  process::sibyll::Decay decay{{particles::Code::PiPlus, particles::Code::PiMinus,
+                                particles::Code::KPlus, particles::Code::KMinus,
+                                particles::Code::K0Long, particles::Code::K0Short}};
   ProcessCut cut(20_GeV);
 
   process::TrackWriter::TrackWriter trackWriter("tracks.dat");
   MyBoundaryCrossingProcess<true> boundaryCrossing("crossings.dat");
 
   // assemble all processes into an ordered process list
-  auto sequence = sibyll << sibyllNuc << decay << cut << boundaryCrossing << trackWriter;
+  auto sequence = sibyll << decay << cut << boundaryCrossing << trackWriter;
 
   // setup particle stack, and add primary particles
   setup::Stack stack;
diff --git a/Documentation/Examples/cascade_example.cc b/Documentation/Examples/cascade_example.cc
index aa70f3d62dbb880951985bc54754c2017a8ec0e9..66b1aa0b7f51dd51e0e6eff8790b86f448d59913 100644
--- a/Documentation/Examples/cascade_example.cc
+++ b/Documentation/Examples/cascade_example.cc
@@ -12,6 +12,7 @@
 #include <corsika/cascade/Cascade.h>
 #include <corsika/process/ProcessSequence.h>
 #include <corsika/process/energy_loss/EnergyLoss.h>
+#include <corsika/process/stack_inspector/StackInspector.h>
 #include <corsika/process/tracking_line/TrackingLine.h>
 
 #include <corsika/setup/SetupEnvironment.h>
@@ -40,7 +41,6 @@
 
 #include <iostream>
 #include <limits>
-#include <typeinfo>
 
 using namespace corsika;
 using namespace corsika::process;
@@ -238,7 +238,7 @@ public:
 int main() {
 
   const LengthType height_atmosphere = 112.8_km;
-  
+
   feenableexcept(FE_INVALID);
   // initialize random number sequence(s)
   random::RNGManager::GetInstance().RegisterRandomStream("cascade");
@@ -273,8 +273,8 @@ int main() {
   universe.AddChild(std::move(outerMedium));
 
   // setup processes, decays and interactions
-  tracking_line::TrackingLine<setup::Stack, setup::Trajectory> tracking(env);
-  // stack_inspector::StackInspector<setup::Stack> stackInspect(true);
+  tracking_line::TrackingLine tracking;
+  stack_inspector::StackInspector<setup::Stack> stackInspect(true);
 
   const std::vector<particles::Code> trackedHadrons = {
       particles::Code::PiPlus, particles::Code::PiMinus, particles::Code::KPlus,
@@ -282,17 +282,18 @@ int main() {
 
   random::RNGManager::GetInstance().RegisterRandomStream("s_rndm");
   random::RNGManager::GetInstance().RegisterRandomStream("pythia");
-  process::sibyll::Interaction sibyll(env);
-  process::sibyll::NuclearInteraction sibyllNuc(env, sibyll);
+  process::sibyll::Interaction sibyll;
+  process::sibyll::NuclearInteraction sibyllNuc(sibyll, env);
   process::sibyll::Decay decay(trackedHadrons);
   ProcessCut cut(20_GeV);
-  ObservationLevel obsLevel(height_atmosphere - 2000_m);//1400_m);
+  ObservationLevel obsLevel(height_atmosphere - 2000_m); // 1400_m);
 
   process::TrackWriter::TrackWriter trackWriter("tracks.dat");
   process::EnergyLoss::EnergyLoss eLoss;
 
   // assemble all processes into an ordered process list
-  auto sequence = sibyll << sibyllNuc << decay << eLoss << cut << trackWriter; // << obsLevel
+  auto sequence = stackInspect << sibyll << sibyllNuc << decay << eLoss << cut
+                               << trackWriter;
 
   // setup particle stack, and add primary particle
   setup::Stack stack;
@@ -301,7 +302,7 @@ int main() {
   const int nuclA = 4;
   const int nuclZ = int(nuclA / 2.15 + 0.7);
   const HEPMassType mass = GetNucleusMass(nuclA, nuclZ);
-  const HEPEnergyType E0 = nuclA * 10_TeV;
+  const HEPEnergyType E0 = nuclA * 1_TeV;
   double theta = 0.;
   double phi = 0.;
 
diff --git a/Documentation/Examples/cascade_proton_example.cc b/Documentation/Examples/cascade_proton_example.cc
index 7cbfda4c0c4e1379418b8f39157e143ece4a335c..743f8f007b0fbfd594cb209d1d580444a25aba21 100644
--- a/Documentation/Examples/cascade_proton_example.cc
+++ b/Documentation/Examples/cascade_proton_example.cc
@@ -12,7 +12,6 @@
 #include <corsika/cascade/Cascade.h>
 #include <corsika/process/ProcessSequence.h>
 #include <corsika/process/hadronic_elastic_model/HadronicElasticModel.h>
-#include <corsika/process/stack_inspector/StackInspector.h>
 #include <corsika/process/tracking_line/TrackingLine.h>
 
 #include <corsika/setup/SetupStack.h>
@@ -58,7 +57,7 @@ using namespace corsika::environment;
 using namespace std;
 using namespace corsika::units::si;
 
-class ProcessCut : public process::ContinuousProcess<ProcessCut> {
+class ProcessCut : public process::SecondariesProcess<ProcessCut> {
 
   HEPEnergyType fECut;
 
@@ -152,47 +151,38 @@ public:
     return is_inv;
   }
 
-  template <typename Particle>
-  LengthType MaxStepLength(Particle& p, setup::Trajectory&) const {
-    cout << "ProcessCut: MinStep: pid: " << p.GetPID() << endl;
-    cout << "ProcessCut: MinStep: energy (GeV): " << p.GetEnergy() / 1_GeV << endl;
-    const Code pid = p.GetPID();
-    if (isEmParticle(pid) || isInvisible(pid) || isBelowEnergyCut(p)) {
-      cout << "ProcessCut: MinStep: next cut: " << 0. << endl;
-      return 0_m;
-    } else {
-      LengthType next_step = 1_m * std::numeric_limits<double>::infinity();
-      cout << "ProcessCut: MinStep: next cut: " << next_step << endl;
-      return next_step;
-    }
-  }
-
-  template <typename Particle, typename Stack>
-  EProcessReturn DoContinuous(Particle& p, setup::Trajectory&, Stack&) {
-    const Code pid = p.GetPID();
-    HEPEnergyType energy = p.GetEnergy();
-    cout << "ProcessCut: DoContinuous: " << pid << " E= " << energy
-         << ", EcutTot=" << (fEmEnergy + fInvEnergy + fEnergy) / 1_GeV << " GeV" << endl;
-    EProcessReturn ret = EProcessReturn::eOk;
-    if (isEmParticle(pid)) {
-      cout << "removing em. particle..." << endl;
-      fEmEnergy += energy;
-      fEmCount += 1;
-      // p.Delete();
-      ret = EProcessReturn::eParticleAbsorbed;
-    } else if (isInvisible(pid)) {
-      cout << "removing inv. particle..." << endl;
-      fInvEnergy += energy;
-      fInvCount += 1;
-      // p.Delete();
-      ret = EProcessReturn::eParticleAbsorbed;
-    } else if (isBelowEnergyCut(p)) {
-      cout << "removing low en. particle..." << endl;
-      fEnergy += energy;
-      // p.Delete();
-      ret = EProcessReturn::eParticleAbsorbed;
+  template <typename TSecondaries>
+  EProcessReturn DoSecondaries(TSecondaries& vS) {
+    auto p = vS.begin();
+    while (p != vS.end()) {
+      const Code pid = p.GetPID();
+      HEPEnergyType energy = p.GetEnergy();
+      cout << "ProcessCut: DoSecondaries: " << pid << " E= " << energy
+           << ", EcutTot=" << (fEmEnergy + fInvEnergy + fEnergy) / 1_GeV << " GeV"
+           << endl;
+      if (isEmParticle(pid)) {
+        cout << "removing em. particle..." << endl;
+        fEmEnergy += energy;
+        fEmCount += 1;
+        p.Delete();
+      } else if (isInvisible(pid)) {
+        cout << "removing inv. particle..." << endl;
+        fInvEnergy += energy;
+        fInvCount += 1;
+        p.Delete();
+      } else if (isBelowEnergyCut(p)) {
+        cout << "removing low en. particle..." << endl;
+        fEnergy += energy;
+        p.Delete();
+      } else if (p.GetTime() > 10_ms) {
+        cout << "removing OLD particle..." << endl;
+        fEnergy += energy;
+        p.Delete();
+      } else {
+        ++p; // next entry in SecondaryView
+      }
     }
-    return ret;
+    return EProcessReturn::eOk;
   }
 
   void Init() {
@@ -229,27 +219,26 @@ int main() {
   random::RNGManager::GetInstance().RegisterRandomStream("cascade");
 
   // setup environment, geometry
-  environment::Environment env;
+  using EnvType = Environment<setup::IEnvironmentModel>;
+  EnvType env;
   auto& universe = *(env.GetUniverse());
 
-  auto theMedium = environment::Environment::CreateNode<Sphere>(
-      Point{env.GetCoordinateSystem(), 0_m, 0_m, 0_m},
-      1_km * std::numeric_limits<double>::infinity());
+  auto theMedium =
+      EnvType::CreateNode<Sphere>(Point{env.GetCoordinateSystem(), 0_m, 0_m, 0_m},
+                                  1_km * std::numeric_limits<double>::infinity());
 
-  using MyHomogeneousModel = environment::HomogeneousMedium<environment::IMediumModel>;
+  using MyHomogeneousModel = HomogeneousMedium<IMediumModel>;
   theMedium->SetModelProperties<MyHomogeneousModel>(
       1_kg / (1_m * 1_m * 1_m),
-      environment::NuclearComposition(
-          std::vector<particles::Code>{particles::Code::Hydrogen},
-          std::vector<float>{(float)1.}));
+      NuclearComposition(std::vector<particles::Code>{particles::Code::Hydrogen},
+                         std::vector<float>{(float)1.}));
 
   universe.AddChild(std::move(theMedium));
 
   const CoordinateSystem& rootCS = env.GetCoordinateSystem();
 
   // setup processes, decays and interactions
-  tracking_line::TrackingLine<setup::Stack, setup::Trajectory> tracking(env);
-  stack_inspector::StackInspector<setup::Stack> p0(true);
+  tracking_line::TrackingLine tracking;
 
   const std::vector<particles::Code> trackedHadrons = {
       particles::Code::PiPlus, particles::Code::PiMinus, particles::Code::KPlus,
@@ -258,7 +247,7 @@ int main() {
   random::RNGManager::GetInstance().RegisterRandomStream("s_rndm");
   random::RNGManager::GetInstance().RegisterRandomStream("pythia");
   //  process::sibyll::Interaction sibyll(env);
-  process::pythia::Interaction pythia(env);
+  process::pythia::Interaction pythia;
   //  process::sibyll::NuclearInteraction sibyllNuc(env, sibyll);
   //  process::sibyll::Decay decay(trackedHadrons);
   process::pythia::Decay decay(trackedHadrons);
@@ -271,10 +260,8 @@ int main() {
   process::TrackWriter::TrackWriter trackWriter("tracks.dat");
 
   // assemble all processes into an ordered process list
-  // auto sequence = p0 << sibyll << decay << hadronicElastic << cut << trackWriter;
-  //  auto sequence = p0 << sibyll << sibyllNuc << decay << cut << trackWriter;
-
-  auto sequence = p0 << pythia << decay << cut << trackWriter;
+  // auto sequence = sibyll << decay << hadronicElastic << cut << trackWriter;
+  auto sequence = pythia << decay << cut << trackWriter;
 
   // cout << "decltype(sequence)=" << type_id_with_cvr<decltype(sequence)>().pretty_name()
   // << "\n";
diff --git a/Documentation/Examples/vertical_EAS.cc b/Documentation/Examples/vertical_EAS.cc
index 6c4036debdcfe1d46f5350321f06016ebdf7cd16..efeb157b75b066746aa0e7e0c1ae2506739e866a 100644
--- a/Documentation/Examples/vertical_EAS.cc
+++ b/Documentation/Examples/vertical_EAS.cc
@@ -13,7 +13,6 @@
 #include <corsika/process/ProcessSequence.h>
 #include <corsika/process/energy_loss/EnergyLoss.h>
 #include <corsika/process/hadronic_elastic_model/HadronicElasticModel.h>
-#include <corsika/process/stack_inspector/StackInspector.h>
 #include <corsika/process/tracking_line/TrackingLine.h>
 
 #include <corsika/setup/SetupStack.h>
@@ -245,16 +244,17 @@ int main() {
   random::RNGManager::GetInstance().RegisterRandomStream("cascade");
 
   // setup environment, geometry
-  environment::Environment env;
+  using EnvType = Environment<setup::IEnvironmentModel>;
+  EnvType env;
   auto& universe = *(env.GetUniverse());
 
-  auto theMedium = environment::Environment::CreateNode<Sphere>(
-      Point{env.GetCoordinateSystem(), 0_m, 0_m, 0_m},
-      1_km * std::numeric_limits<double>::infinity());
+  auto theMedium =
+      EnvType::CreateNode<Sphere>(Point{env.GetCoordinateSystem(), 0_m, 0_m, 0_m},
+                                  1_km * std::numeric_limits<double>::infinity());
 
   // fraction of oxygen
   const float fox = 0.20946;
-  using MyHomogeneousModel = environment::HomogeneousMedium<environment::IMediumModel>;
+  using MyHomogeneousModel = HomogeneousMedium<environment::IMediumModel>;
   theMedium->SetModelProperties<MyHomogeneousModel>(
       1_kg / (1_m * 1_m * 1_m),
       environment::NuclearComposition(
@@ -267,16 +267,15 @@ int main() {
   const CoordinateSystem& rootCS = env.GetCoordinateSystem();
 
   // setup processes, decays and interactions
-  tracking_line::TrackingLine<setup::Stack, setup::Trajectory> tracking(env);
-  // stack_inspector::StackInspector<setup::Stack> stackInspect(true);
+  tracking_line::TrackingLine tracking;
 
   const std::vector<particles::Code> trackedHadrons = {
       particles::Code::PiPlus, particles::Code::PiMinus, particles::Code::KPlus,
       particles::Code::KMinus, particles::Code::K0Long,  particles::Code::K0Short};
 
   random::RNGManager::GetInstance().RegisterRandomStream("s_rndm");
-  process::sibyll::Interaction sibyll(env);
-  process::sibyll::NuclearInteraction sibyllNuc(env, sibyll);
+  process::sibyll::Interaction sibyll;
+  process::sibyll::NuclearInteraction sibyllNuc(sibyll, env);
   process::sibyll::Decay decay(trackedHadrons);
   // random::RNGManager::GetInstance().RegisterRandomStream("pythia");
   // process::pythia::Decay decay(trackedHadrons);
@@ -291,11 +290,8 @@ int main() {
   process::EnergyLoss::EnergyLoss eLoss;
 
   // assemble all processes into an ordered process list
-  // auto sequence = stackInspect << sibyll << decay << hadronicElastic << cut <<
-  // trackWriter; auto sequence = stackInspect << sibyll << sibyllNuc << decay << eLoss <<
   // cut << trackWriter;
   auto sequence = sibyll << sibyllNuc << decay << eLoss << cut << obsLevel;
-  // auto sequence = stackInspect << sibyll << sibyllNuc << decay << eLoss << cut;
 
   // cout << "decltype(sequence)=" << type_id_with_cvr<decltype(sequence)>().pretty_name()
   // << "\n";
diff --git a/Environment/FlatAtmosphere/FlatAtmosphere.h b/Environment/FlatAtmosphere/FlatAtmosphere.h
index 6839def48c2f6fddfafd0beb5fd4ca46058ebd09..4227e0de4f5490ee2ac5a90857d68c5653e865ec 100644
--- a/Environment/FlatAtmosphere/FlatAtmosphere.h
+++ b/Environment/FlatAtmosphere/FlatAtmosphere.h
@@ -8,3 +8,5 @@
  * Licence version 3 (GPL Version 3). See file LICENSE for a full version of
  * the license.
  */
+
+
diff --git a/Environment/FlatExponential.h b/Environment/FlatExponential.h
index 19e42c725c4b5204dc9c6fc166f9be00f44bdb7a..61fa2dced76357946bccfc9fc2951752361c9a42 100644
--- a/Environment/FlatExponential.h
+++ b/Environment/FlatExponential.h
@@ -1,5 +1,6 @@
+
 /*
- * (c) Copyright 2019 CORSIKA Project, corsika-project@lists.kit.edu
+ * (c) Copyright 2018 CORSIKA Project, corsika-project@lists.kit.edu
  *
  * See file AUTHORS for a list of contributors.
  *
diff --git a/Environment/VolumeTreeNode.h b/Environment/VolumeTreeNode.h
index 7c32076369e63e2982e8fe744a2a23bf2395a268..7a8b2e785f134ba59546e5622366a03c8f7554a4 100644
--- a/Environment/VolumeTreeNode.h
+++ b/Environment/VolumeTreeNode.h
@@ -108,7 +108,7 @@ namespace corsika::environment {
 
     auto const& GetModelProperties() const { return *fModelProperties; }
 
-    auto const& HasModelProperties() const { return fModelProperties.get() != nullptr; }
+    bool HasModelProperties() const { return fModelProperties.get() != nullptr; }
 
     template <typename ModelProperties, typename... Args>
     auto SetModelProperties(Args&&... args) {
diff --git a/Framework/Cascade/CMakeLists.txt b/Framework/Cascade/CMakeLists.txt
index 2903d814ce8ad3eec8ba995519ac4745faeb644d..cce178637582bb48a8b17d1017bc489802c192aa 100644
--- a/Framework/Cascade/CMakeLists.txt
+++ b/Framework/Cascade/CMakeLists.txt
@@ -43,7 +43,7 @@ target_link_libraries (
   CORSIKArandom
   ProcessSibyll
   CORSIKAcascade
-#  ProcessStackInspector
+  ProcessStackInspector
   ProcessTrackingLine
   ProcessNullModel
   CORSIKAstackinterface
diff --git a/Framework/Cascade/Cascade.h b/Framework/Cascade/Cascade.h
index d3ee524313d5af50c4bbb50ce34e00cd7a6218b7..75f29e4ed51bc70d7d31d4917ef4c186baee4bef 100644
--- a/Framework/Cascade/Cascade.h
+++ b/Framework/Cascade/Cascade.h
@@ -36,6 +36,9 @@
 #include <limits>
 #include <type_traits>
 
+#include <boost/type_index.hpp>
+using boost::typeindex::type_id_with_cvr;
+
 /**
  * The cascade namespace assembles all objects needed to simulate full particles cascades.
  */
@@ -54,6 +57,7 @@ namespace corsika::cascade {
    * <code>auto GetTrack(Particle const& p)</auto>,
    * with the return type <code>geometry::Trajectory<corsika::geometry::Line>
    * </code>
+   *
    * <b>TProcessList</b> must be a ProcessSequence.   *
    * <b>Stack</b> is the storage object for particle data, i.e. with
    * Particle class type <code>Stack::ParticleType</code>
@@ -61,7 +65,12 @@ namespace corsika::cascade {
    *
    */
 
-  template <typename TTracking, typename TProcessList, typename TStack>
+  template <typename TTracking, typename TProcessList, typename TStack,
+            /*
+              TStackView is needed as template parameter because of issue 161 and the
+              inability of clang to understand "MakeView" so far.
+             */
+            typename TStackView = corsika::setup::StackView>
   class Cascade {
     using Particle = typename TStack::ParticleType;
     using VolumeTreeNode =
@@ -115,6 +124,7 @@ namespace corsika::cascade {
         while (!fStack.IsEmpty()) {
           auto pNext = fStack.GetNextParticle();
           Step(pNext);
+          fProcessSequence.DoStack(fStack);
         }
         // do cascade equations, which can put new particles on Stack,
         // thus, the double loop
@@ -139,6 +149,7 @@ namespace corsika::cascade {
 
       // determine geometric tracking
       auto [step, geomMaxLength, nextVol] = fTracking.GetTrack(vParticle);
+      [[maybe_unused]] auto const& dummy_nextVol = nextVol;
 
       // determine combined total interaction length (inverse)
       InverseGrammageType const total_inv_lambda =
@@ -151,7 +162,7 @@ namespace corsika::cascade {
       std::cout << "total_inv_lambda=" << total_inv_lambda
                 << ", next_interact=" << next_interact << std::endl;
 
-      auto const* currentLogicalNode = particle.GetNode();
+      auto const* currentLogicalNode = vParticle.GetNode();
 
       // assert that particle stays outside void Universe if it has no
       // model properties set
@@ -217,25 +228,17 @@ namespace corsika::cascade {
         important to use projectle (and not vParticle) for Interaction,
         and Decay!
        */
-      setup::StackView secondaries(vParticle);
-      [[maybe_unused]] auto projectile = secondaries.GetProjectile();
 
-      /*
-        Create SecondaryView object on Stack. The data container
-        remains untouched and identical, and 'projectil' is identical
-        to 'vParticle' above this line. However,
-        projectil.AddSecondaries populate the SecondaryView, which can
-        then be used afterwards for further processing. Thus: it is
-        important to use projectle (and not vParticle) for Interaction,
-        and Decay!
-       */
-      setup::StackView secondaries(vParticle);
+      TStackView secondaries(vParticle);
       [[maybe_unused]] auto projectile = secondaries.GetProjectile();
 
-      if (min_distance < distance_max) { // interaction to happen within geometric limit
-        // check whether decay or interaction limits this step
-
       if (min_distance < geomMaxLength) { // interaction to happen within geometric limit
+
+        // check whether decay or interaction limits this step the
+        // outcome of decay or interaction MAY be a) new particles in
+        // secondaries, b) the projectile particle deleted (or
+        // changed)
+
         if (min_distance == distance_interact) {
           std::cout << "collide" << std::endl;
 
@@ -255,26 +258,31 @@ namespace corsika::cascade {
           random::UniformRealDistribution<InverseTimeType> uniDist(actual_decay_time);
           const auto sample_process = uniDist(fRNG);
           InverseTimeType inv_decay_count = 0 / second;
-          fProcessSequence.SelectDecay(vParticle, projectile, sample_process, inv_decay_count);
+          fProcessSequence.SelectDecay(vParticle, projectile, sample_process,
+                                       inv_decay_count);
         } else { // step-length limitation within volume
           std::cout << "step-length limitation" << std::endl;
         }
-	
-	fProcessSequence.DoSecondaries(secondaries);
-        vParticle.Delete(); // last thing in Step function
+
+        fProcessSequence.DoSecondaries(secondaries);
+        vParticle.Delete(); // todo: this should be reviewed. Where
+                            // exactly are particles best deleted, and
+                            // where they should NOT be
+                            // deleted... maybe Delete function should
+                            // be "protected" and not accessible to physics
 
         auto const assertion = [&] {
           auto const* numericalNodeAfterStep =
-              fEnvironment.GetUniverse()->GetContainingNode(particle.GetPosition());
+              fEnvironment.GetUniverse()->GetContainingNode(vParticle.GetPosition());
           return numericalNodeAfterStep == currentLogicalNode;
         };
 
         assert(assertion()); // numerical and logical nodes don't match
       } else {               // boundary crossing, step is limited by volume boundary
         std::cout << "boundary crossing! next node = " << nextVol << std::endl;
-        particle.SetNode(nextVol);
+        vParticle.SetNode(nextVol);
         // DoBoundary may delete the particle (or not)
-        fProcessSequence.DoBoundaryCrossing(particle, *currentLogicalNode, *nextVol);
+        fProcessSequence.DoBoundaryCrossing(vParticle, *currentLogicalNode, *nextVol);
       }
     }
 
diff --git a/Framework/Cascade/testCascade.cc b/Framework/Cascade/testCascade.cc
index 1a46850c65c81570acd42bc50ec88d4f58344351..3f95c7a3a63fa6766dd6ed2e26bc5a38e2640a44 100644
--- a/Framework/Cascade/testCascade.cc
+++ b/Framework/Cascade/testCascade.cc
@@ -9,8 +9,6 @@
  * the license.
  */
 
-#include <limits>
-
 #include <corsika/cascade/testCascade.h>
 
 #include <corsika/cascade/Cascade.h>
@@ -29,10 +27,6 @@
 #include <corsika/environment/HomogeneousMedium.h>
 #include <corsika/environment/NuclearComposition.h>
 
-#include <corsika/setup/SetupStack.h>
-#include <corsika/setup/SetupTrajectory.h>
-using corsika::setup::Trajectory;
-
 #define CATCH_CONFIG_MAIN // This tells Catch to provide a main() - only do this in one
                           // cpp file
 #include <catch2/catch.hpp>
@@ -44,6 +38,7 @@ using namespace corsika::units::si;
 using namespace corsika::geometry;
 
 #include <iostream>
+#include <limits>
 using namespace std;
 
 auto MakeDummyEnv() {
@@ -52,11 +47,11 @@ auto MakeDummyEnv() {
 
   auto theMedium = TestEnvironmentType::CreateNode<Sphere>(
       Point{env.GetCoordinateSystem(), 0_m, 0_m, 0_m},
-      1_km * std::numeric_limits<double>::infinity());
+      100_km * std::numeric_limits<double>::infinity());
 
   using MyHomogeneousModel = environment::HomogeneousMedium<environment::IMediumModel>;
   theMedium->SetModelProperties<MyHomogeneousModel>(
-      1_g / (1_m * 1_m * 1_m),
+      1_g / (1_cm * 1_cm * 1_cm),
       environment::NuclearComposition(
           std::vector<particles::Code>{particles::Code::Proton}, std::vector<float>{1.}));
 
@@ -65,47 +60,75 @@ auto MakeDummyEnv() {
   return env;
 }
 
-class ProcessSplit : public process::ContinuousProcess<ProcessSplit> {
+class ProcessSplit : public process::InteractionProcess<ProcessSplit> {
 
-  int fCount = 0;
   int fCalls = 0;
-  HEPEnergyType fEcrit;
+  GrammageType fX0;
 
 public:
-  ProcessSplit(HEPEnergyType e)
-      : fEcrit(e) {}
+  ProcessSplit(GrammageType const X0)
+      : fX0(X0) {}
 
   template <typename Particle, typename Track>
-  LengthType MaxStepLength(Particle&, Track&) const {
-    return 1_m;
+  corsika::units::si::GrammageType GetInteractionLength(Particle&, Track&) const {
+    return fX0;
   }
 
-  template <typename Particle, typename Track>
-  EProcessReturn DoContinuous(Particle& p, Track&) {
+  template <typename TProjectile>
+  corsika::process::EProcessReturn DoInteraction(TProjectile& vP) {
+    fCalls++;
+    const HEPEnergyType E = vP.GetEnergy();
+    vP.AddSecondary(
+        std::tuple<particles::Code, units::si::HEPEnergyType,
+                   corsika::stack::MomentumVector, geometry::Point, units::si::TimeType>{
+            vP.GetPID(), E / 2, vP.GetMomentum(), vP.GetPosition(), vP.GetTime()});
+    vP.AddSecondary(
+        std::tuple<particles::Code, units::si::HEPEnergyType,
+                   corsika::stack::MomentumVector, geometry::Point, units::si::TimeType>{
+            vP.GetPID(), E / 2, vP.GetMomentum(), vP.GetPosition(), vP.GetTime()});
+    return EProcessReturn::eInteracted;
+  }
+
+  void Init() { fCalls = 0; }
+
+  int GetCalls() const { return fCalls; }
+};
+
+class ProcessCut : public process::SecondariesProcess<ProcessCut> {
+
+  int fCount = 0;
+  int fCalls = 0;
+  HEPEnergyType fEcrit;
+
+public:
+  ProcessCut(HEPEnergyType e)
+      : fEcrit(e) {}
+
+  template <typename TStack>
+  EProcessReturn DoSecondaries(TStack& vS) {
     fCalls++;
-    HEPEnergyType E = p.GetEnergy();
-    if (E < fEcrit) {
-      p.Delete();
-      fCount++;
-    } else {
-      p.SetEnergy(E / 2);
-      p.AddSecondary(std::tuple<particles::Code, units::si::HEPEnergyType,
-                                corsika::stack::MomentumVector, geometry::Point,
-                                units::si::TimeType>{p.GetPID(), E / 2, p.GetMomentum(),
-                                                     p.GetPosition(), p.GetTime()});
+    auto p = vS.begin();
+    while (p != vS.end()) {
+      HEPEnergyType E = p.GetEnergy();
+      if (E < fEcrit) {
+        p.Delete();
+        fCount++;
+      } else {
+        ++p; // next particle
+      }
     }
+    cout << "ProcessCut::DoSecondaries size=" << vS.GetSize() << " count=" << fCount
+         << endl;
     return EProcessReturn::eOk;
   }
 
   void Init() {
-    fCount = 0;
     fCalls = 0;
+    fCount = 0;
   }
 
   int GetCount() const { return fCount; }
   int GetCalls() const { return fCalls; }
-
-private:
 };
 
 TEST_CASE("Cascade", "[Cascade]") {
@@ -118,12 +141,16 @@ TEST_CASE("Cascade", "[Cascade]") {
   stack_inspector::StackInspector<TestCascadeStack> stackInspect(true);
   null_model::NullModel nullModel;
 
+  const GrammageType X0 = 20_g / square(1_cm);
   const HEPEnergyType Ecrit = 85_MeV;
-  ProcessSplit p1(Ecrit);
-  auto sequence =  nullModel /* << stackInspect*/ << p1;
+  ProcessSplit split(X0);
+  ProcessCut cut(Ecrit);
+  auto sequence = nullModel << stackInspect << split << cut;
   TestCascadeStack stack;
 
-  cascade::Cascade EAS(env, tracking, sequence, stack);
+  cascade::Cascade<tracking_line::TrackingLine, decltype(sequence), TestCascadeStack,
+                   TestCascadeStackView>
+      EAS(env, tracking, sequence, stack);
   CoordinateSystem const& rootCS =
       RootCoordinateSystem::GetInstance().GetRootCoordinateSystem();
 
@@ -138,6 +165,7 @@ TEST_CASE("Cascade", "[Cascade]") {
   EAS.Init();
   EAS.Run();
 
-  CHECK(p1.GetCount() == 2048);
-  CHECK(p1.GetCalls() == 4095);
+  CHECK(cut.GetCount() == 2048);
+  CHECK(cut.GetCalls() == 2047);
+  CHECK(split.GetCalls() == 2047);
 }
diff --git a/Framework/Cascade/testCascade.h b/Framework/Cascade/testCascade.h
index c84d1e14bff303274e648a4d018e711c4ff9dfd5..386a7281f429ad1b9a8ce83de4ed1e5e830ef040 100644
--- a/Framework/Cascade/testCascade.h
+++ b/Framework/Cascade/testCascade.h
@@ -26,8 +26,20 @@ template <typename StackIter>
 using StackWithGeometryInterface = corsika::stack::CombinedParticleInterface<
     corsika::setup::detail::ParticleDataStack::PIType, SetupGeometryDataInterface,
     StackIter>;
+
 using TestCascadeStack = corsika::stack::CombinedStack<
     typename corsika::setup::detail::ParticleDataStack::StackImpl,
     GeometryData<TestEnvironmentType>, StackWithGeometryInterface>;
 
+/*
+  See also Issue 161
+*/
+#if defined(__clang__)
+using TestCascadeStackView =
+    corsika::stack::SecondaryView<typename TestCascadeStack::StackImpl,
+                                  StackWithGeometryInterface>;
+#elif defined(__GNUC__) || defined(__GNUG__)
+using TestCascadeStackView = corsika::stack::MakeView<TestCascadeStack>::type;
+#endif
+
 #endif
diff --git a/Framework/ProcessSequence/BaseProcess.h b/Framework/ProcessSequence/BaseProcess.h
index 8b4014478f5ebef33e4acd76f6b7315f2c1e5041..6733fcf9a9f66a53c3a4d55326cdc37eabbcc314 100644
--- a/Framework/ProcessSequence/BaseProcess.h
+++ b/Framework/ProcessSequence/BaseProcess.h
@@ -13,6 +13,7 @@
 #define _include_corsika_baseprocess_h_
 
 #include <corsika/process/ProcessReturn.h> // for convenience
+#include <type_traits>
 
 namespace corsika::process {
 
diff --git a/Framework/ProcessSequence/CMakeLists.txt b/Framework/ProcessSequence/CMakeLists.txt
index ac49b2b38045858ab2eb50377145ceda457ebff6..33aad8236f6b2943d083fd95addcea1698700d43 100644
--- a/Framework/ProcessSequence/CMakeLists.txt
+++ b/Framework/ProcessSequence/CMakeLists.txt
@@ -15,6 +15,7 @@ set (
   ContinuousProcess.h
   SecondariesProcess.h
   InteractionProcess.h
+  StackProcess.h
   DecayProcess.h
   ProcessSequence.h
   ProcessReturn.h
diff --git a/Framework/ProcessSequence/ProcessSequence.h b/Framework/ProcessSequence/ProcessSequence.h
index 51380c15bd89896cf2aa7c240e92ec44111fe101..ee154d8ae2810c35aa7b12b4c8ba25162504e3de 100644
--- a/Framework/ProcessSequence/ProcessSequence.h
+++ b/Framework/ProcessSequence/ProcessSequence.h
@@ -19,6 +19,7 @@
 #include <corsika/process/InteractionProcess.h>
 #include <corsika/process/ProcessReturn.h>
 #include <corsika/process/SecondariesProcess.h>
+#include <corsika/process/StackProcess.h>
 #include <corsika/units/PhysicalUnits.h>
 
 #include <cmath>
@@ -118,16 +119,16 @@ namespace corsika::process {
       return ret;
     }
 
-    template <typename TSecondaries>
-    EProcessReturn DoSecondaries(TSecondaries& vS) {
+    template <typename TStack>
+    EProcessReturn DoStack(TStack& vS) {
       EProcessReturn ret = EProcessReturn::eOk;
-      if constexpr (std::is_base_of<SecondariesProcess<T1type>, T1type>::value ||
+      if constexpr (std::is_base_of<StackProcess<T1type>, T1type>::value ||
                     is_process_sequence<T1>::value) {
-        ret |= A.DoSecondaries(vS);
+        ret |= A.DoStack(vS);
       }
-      if constexpr (std::is_base_of<SecondariesProcess<T2type>, T2type>::value ||
+      if constexpr (std::is_base_of<StackProcess<T2type>, T2type>::value ||
                     is_process_sequence<T2>::value) {
-        ret |= B.DoSecondaries(vS);
+        ret |= B.DoStack(vS);
       }
       return ret;
     }
diff --git a/Framework/ProcessSequence/StackProcess.h b/Framework/ProcessSequence/StackProcess.h
new file mode 100644
index 0000000000000000000000000000000000000000..0b8775d716154d97bf6e7bea646fcbbae52fdcdd
--- /dev/null
+++ b/Framework/ProcessSequence/StackProcess.h
@@ -0,0 +1,48 @@
+
+/*
+ * (c) Copyright 2018 CORSIKA Project, corsika-project@lists.kit.edu
+ *
+ * See file AUTHORS for a list of contributors.
+ *
+ * This software is distributed under the terms of the GNU General Public
+ * Licence version 3 (GPL Version 3). See file LICENSE for a full version of
+ * the license.
+ */
+
+#ifndef _include_corsika_stackprocess_h_
+#define _include_corsika_stackprocess_h_
+
+#include <corsika/process/ProcessReturn.h> // for convenience
+#include <corsika/setup/SetupTrajectory.h>
+#include <corsika/units/PhysicalUnits.h>
+
+namespace corsika::process {
+
+  /**
+     \class StackProcess
+
+     The structural base type of a process object in a
+     ProcessSequence. Both, the ProcessSequence and all its elements
+     are of type StackProcess<T>
+
+   */
+
+  template <typename derived>
+  struct StackProcess {
+
+    derived& GetRef() { return static_cast<derived&>(*this); }
+    const derived& GetRef() const { return static_cast<const derived&>(*this); }
+
+    /// here starts the interface-definition part
+    // -> enforce derived to implement DoStack...
+    template <typename TStack>
+    inline EProcessReturn DoStack(TStack&);
+  };
+
+  // overwrite the default trait class, to mark BaseProcess<T> as useful process
+  template <class T>
+  std::true_type is_process_impl(const StackProcess<T>* impl);
+
+} // namespace corsika::process
+
+#endif
diff --git a/Framework/StackInterface/CombinedStack.h b/Framework/StackInterface/CombinedStack.h
index 7633d383bef2eb1a6131d10e3caf282d606e1adf..8b987d5100732a7a339a23d6fadd3530870bb2ef 100644
--- a/Framework/StackInterface/CombinedStack.h
+++ b/Framework/StackInterface/CombinedStack.h
@@ -41,6 +41,10 @@ namespace corsika::stack {
   class CombinedParticleInterface
       : public ParticleInterfaceB<ParticleInterfaceA<StackIterator>> {
 
+    // template<template <typename> typename _PI>
+    // template <typename StackDataType, template <typename> typename ParticleInterface>
+    // template<typename T1, template <typename> typename T2> friend class Stack<T1, T2>;
+
     using PI_C =
         CombinedParticleInterface<ParticleInterfaceA, ParticleInterfaceB, StackIterator>;
     using PI_A = ParticleInterfaceA<StackIterator>;
diff --git a/Framework/StackInterface/ParticleBase.h b/Framework/StackInterface/ParticleBase.h
index e3504fbeff43ca80f584b179db7eb8bd907609c8..04c9184ba5187111e44ffae0902a7352950498da 100644
--- a/Framework/StackInterface/ParticleBase.h
+++ b/Framework/StackInterface/ParticleBase.h
@@ -52,7 +52,6 @@ namespace corsika::stack {
     ParticleBase() = default;
 
   private:
-    /*
     // those copy constructors and assigments should never be implemented
     ParticleBase(ParticleBase&) = delete;
     ParticleBase operator=(ParticleBase&) = delete;
@@ -60,7 +59,7 @@ namespace corsika::stack {
     ParticleBase operator=(ParticleBase&&) = delete;
     ParticleBase(const ParticleBase&) = delete;
     ParticleBase operator=(const ParticleBase&) = delete;
-    */
+
   public:
     /**
      * Delete this particle on the stack. The corresponding iterator
@@ -88,7 +87,7 @@ namespace corsika::stack {
       return static_cast<const StackIterator&>(*this);
     }
 
-    //  protected:
+  protected:
     /**
         @name Access to underlying stack fData, these are service
         function for user classes. User code can only rely on GetIndex
@@ -107,26 +106,6 @@ namespace corsika::stack {
     ///@}
   };
 
-  template <typename T>
-  class ParticleBaseAdd {
-
-  public:
-    ParticleBaseAdd() = default;
-
-    using T::GetIndex;
-    using T::GetStackData;
-
-  public:
-    /*
-    template <typename... Args1, typename... Args2>
-    void SetParticleData(Args1... args1, Args2... args2) {
-      T::SetParticleData(args1...);
-    }
-    template <typename... Args1, typename... Args2>
-    void SetParticleData(T& p, Args1... args1, Args2... args2) {}
-    */
-  };
-
 } // namespace corsika::stack
 
 #endif
diff --git a/Framework/StackInterface/SecondaryView.h b/Framework/StackInterface/SecondaryView.h
index 3e781f8e6c70edbca333c5ffd53d6f630961678d..563de91539ee39fd32730eb1baae6144f0e8d634 100644
--- a/Framework/StackInterface/SecondaryView.h
+++ b/Framework/StackInterface/SecondaryView.h
@@ -14,6 +14,7 @@
 
 #include <corsika/stack/Stack.h>
 
+#include <stdexcept>
 #include <vector>
 
 namespace corsika::stack {
@@ -53,7 +54,7 @@ namespace corsika::stack {
    */
 
   template <typename StackDataType, template <typename> typename ParticleInterface>
-  class SecondaryView : public Stack<StackDataType&, ParticleInterface> {
+  class SecondaryView : public corsika::stack::Stack<StackDataType&, ParticleInterface> {
 
     using ViewType = SecondaryView<StackDataType, ParticleInterface>;
 
@@ -100,9 +101,13 @@ namespace corsika::stack {
      * new stack.
      */
     template <typename... Args>
-    SecondaryView(Args... args);
+    SecondaryView(Args... args) = delete;
 
   public:
+    /**
+       SecondaryView can only be constructed passing it a valid
+       StackIterator to another Stack object
+     **/
     SecondaryView(StackIteratorValue& vI)
         : Stack<StackDataType&, ParticleInterface>(vI.GetStackData())
         , fProjectileIndex(vI.GetIndex()) {}
@@ -207,6 +212,21 @@ namespace corsika::stack {
     std::vector<unsigned int> fIndices;
   };
 
+  /*
+    See Issue 161
+
+    unfortunately clang does not support this in the same way (yet) as
+    gcc, so we have to distinguish here. If clang cataches up, we
+    could remove the #if here and elsewhere. The gcc code is much more
+    generic and universal.
+  */
+#if not defined(__clang__) && defined(__GNUC__) || defined(__GNUG__)
+  template <typename S, template <typename> typename _PIType = S::template PIType>
+  struct MakeView {
+    using type = corsika::stack::SecondaryView<typename S::StackImpl, _PIType>;
+  };
+#endif
+
 } // namespace corsika::stack
 
 #endif
diff --git a/Framework/StackInterface/Stack.h b/Framework/StackInterface/Stack.h
index 72f3a72fe2d9c5078f893b3f815ed880fd515118..a666e0ff02817164564576245b990348f1dfb48c 100644
--- a/Framework/StackInterface/Stack.h
+++ b/Framework/StackInterface/Stack.h
@@ -13,12 +13,11 @@
 #define _include_Stack_h__
 
 #include <corsika/stack/StackIteratorInterface.h>
+#include <corsika/stack/SecondaryView.h>
 
 #include <stdexcept>
 #include <type_traits>
 
-#include <corsika/stack/SecondaryView.h>
-
 /**
    All classes around management of particles on a stack.
  */
@@ -85,6 +84,10 @@ namespace corsika::stack {
      * This constructor takes any argument and passes it on to the
      * StackDataType user class. If the user did not provide a suited
      * constructor this will fail with an error message.
+     *
+     * Furthermore, this is disabled with enable_if for SecondaryView
+     * stacks, where the inner data container is always a reference
+     * and cannot be initialized here.
      */
     template <
         typename... Args, typename _StackDataType = StackDataType,
diff --git a/Framework/StackInterface/StackIteratorInterface.h b/Framework/StackInterface/StackIteratorInterface.h
index 4e5cc6d059967d8d64ffdb51a2474052e7bd0d2b..03c59cb44c1d9b7cc74f18fce20cd0ceaaac687f 100644
--- a/Framework/StackInterface/StackIteratorInterface.h
+++ b/Framework/StackInterface/StackIteratorInterface.h
@@ -14,8 +14,6 @@
 
 #include <corsika/stack/ParticleBase.h>
 
-#include <type_traits>
-
 namespace corsika::stack {
 
   template <typename StackDataType, template <typename> typename ParticleInterface>
@@ -91,10 +89,20 @@ namespace corsika::stack {
     StackIteratorInterface() = delete;
 
   public:
+    StackIteratorInterface(StackIteratorInterface const& vR)
+        : fIndex(vR.fIndex)
+        , fData(vR.fData) {}
+
+    StackIteratorInterface& operator=(StackIteratorInterface const& vR) {
+      fIndex = vR.fIndex;
+      fData = vR.fData;
+      return *this;
+    }
+
     /** iterator must always point to data, with an index:
-        @param data reference to the stack [rw]
-        @param index index on stack
-     */
+          @param data reference to the stack [rw]
+          @param index index on stack
+       */
     StackIteratorInterface(StackType& data, const unsigned int index)
         : fIndex(index)
         , fData(&data) {}
diff --git a/Framework/StackInterface/testCombinedStack.cc b/Framework/StackInterface/testCombinedStack.cc
index 9ae2f8ad60c8cee4028466e977edb37b6e7f508f..fbe4a031c928da4ea5a6c326ad1a98c903933972 100644
--- a/Framework/StackInterface/testCombinedStack.cc
+++ b/Framework/StackInterface/testCombinedStack.cc
@@ -335,20 +335,18 @@ using StackTest2 = CombinedStack<typename StackTest::StackImpl, TestStackData3,
 #if defined(__clang__)
 using StackTestView = SecondaryView<TestStackData, TestParticleInterface>;
 #elif defined(__GNUC__) || defined(__GNUG__)
-template <typename S, template <typename> typename _PIType = S::template PIType>
-struct MakeView {
-  using type = corsika::stack::SecondaryView<typename S::StackImpl, _PIType>;
-};
-using StackTestView = MakeView<StackTest2>::type;
+using StackTestView = corsika::stack::MakeView<StackTest2>::type;
 #endif
 
+using Particle2 = typename StackTest2::ParticleType;
+
 TEST_CASE("Combined Stack - secondary view") {
 
   SECTION("create secondaries via secondaryview") {
 
     StackTest2 stack;
     auto particle = stack.AddParticle(std::tuple{9.9});
-
+    // cout << boost::typeindex::type_id_runtime(particle).pretty_name() << endl;
     StackTestView view(particle);
 
     auto projectile = view.GetProjectile();
diff --git a/Framework/StackInterface/testSecondaryView.cc b/Framework/StackInterface/testSecondaryView.cc
index 6f13ceecd1d5f88171a1b6e0574b5e1aaaab2c93..2d2064b64e2e09c96ec5f77ebbf25d50f5d60e9e 100644
--- a/Framework/StackInterface/testSecondaryView.cc
+++ b/Framework/StackInterface/testSecondaryView.cc
@@ -44,13 +44,11 @@ typedef Stack<TestStackData, TestParticleInterface> StackTest;
 #if defined(__clang__)
 using StackTestView = SecondaryView<TestStackData, TestParticleInterface>;
 #elif defined(__GNUC__) || defined(__GNUG__)
-template <typename S, template <typename> typename _PIType = S::template PIType>
-struct MakeView {
-  using type = corsika::stack::SecondaryView<typename S::StackImpl, _PIType>;
-};
 using StackTestView = MakeView<StackTest>::type;
 #endif
 
+using Particle = typename StackTest::ParticleType;
+
 TEST_CASE("SecondaryStack", "[stack]") {
 
   // helper function for sum over stack data
diff --git a/Main/Environment.h b/Main/Environment.h
index 6839def48c2f6fddfafd0beb5fd4ca46058ebd09..4227e0de4f5490ee2ac5a90857d68c5653e865ec 100644
--- a/Main/Environment.h
+++ b/Main/Environment.h
@@ -8,3 +8,5 @@
  * Licence version 3 (GPL Version 3). See file LICENSE for a full version of
  * the license.
  */
+
+
diff --git a/Main/Stack.h b/Main/Stack.h
index 6839def48c2f6fddfafd0beb5fd4ca46058ebd09..4227e0de4f5490ee2ac5a90857d68c5653e865ec 100644
--- a/Main/Stack.h
+++ b/Main/Stack.h
@@ -8,3 +8,5 @@
  * Licence version 3 (GPL Version 3). See file LICENSE for a full version of
  * the license.
  */
+
+
diff --git a/Processes/CMakeLists.txt b/Processes/CMakeLists.txt
index cddec6bd425a19f361346a7e50b6da843a0167c9..d6162179ca3440e788a40a9a6ab0c18edb7d44f6 100644
--- a/Processes/CMakeLists.txt
+++ b/Processes/CMakeLists.txt
@@ -4,7 +4,7 @@ add_subdirectory (Sibyll)
 if (PYTHIA8_FOUND)
   add_subdirectory (Pythia)
 endif (PYTHIA8_FOUND)
-# add_subdirectory (StackInspector)
+add_subdirectory (StackInspector)
 add_subdirectory (TrackWriter)
 add_subdirectory (TrackingLine)
 add_subdirectory (HadronicElasticModel)
diff --git a/Processes/EnergyLoss/EnergyLoss.cc b/Processes/EnergyLoss/EnergyLoss.cc
index 094eec177907048fabd4b70c10bc9b54f49941a8..dde5cf442c175d167cd14f605a04f4e5fd288736 100644
--- a/Processes/EnergyLoss/EnergyLoss.cc
+++ b/Processes/EnergyLoss/EnergyLoss.cc
@@ -125,8 +125,8 @@ namespace corsika::process::EnergyLoss {
 
     // Barkas correction O(Z3) higher-order Born approximation
     // see Appl. Phys. 85 (1999) 1249
-    //double A = 1;
-    //if (p.GetPID() == particles::Code::Nucleus) A = p.GetNuclearA();
+    // double A = 1;
+    // if (p.GetPID() == particles::Code::Nucleus) A = p.GetNuclearA();
     // double const Erel = (p.GetEnergy()-p.GetMass()) / A / 1_keV;
     // double const Llow = 0.01 * Erel;
     // double const Lhigh = 1.5/pow(Erel, 0.4) + 45000./Zmat * pow(Erel, 1.6);
diff --git a/Processes/NullModel/NullModel.h b/Processes/NullModel/NullModel.h
index db157b55fefdc1ed584eb7f7437bc45d9d2986b0..d3a820da41ede79dfd40669e7da6d15faaa8cf79 100644
--- a/Processes/NullModel/NullModel.h
+++ b/Processes/NullModel/NullModel.h
@@ -12,11 +12,12 @@
 #ifndef _Physics_NullModel_NullModel_h_
 #define _Physics_NullModel_NullModel_h_
 
-#include <corsika/process/ContinuousProcess.h>
+#include <corsika/process/BaseProcess.h>
+#include <corsika/units/PhysicalUnits.h>
 
 namespace corsika::process::null_model {
 
-  class NullModel : public corsika::process::ContinuousProcess<NullModel> {
+  class NullModel : public corsika::process::BaseProcess<NullModel> {
     corsika::units::si::LengthType const fMaxStepLength;
 
   public:
diff --git a/Processes/NullModel/testNullModel.cc b/Processes/NullModel/testNullModel.cc
index 4ab4c0422d5638703e5dff5d6e81f9eabaa14819..930d5979fec7bbcc728212b74e944f7dd11599cf 100644
--- a/Processes/NullModel/testNullModel.cc
+++ b/Processes/NullModel/testNullModel.cc
@@ -39,16 +39,12 @@ TEST_CASE("NullModel", "[processes]") {
   geometry::Trajectory<geometry::Line> track(line, 10_s);
 
   setup::Stack stack;
-  setup::Stack::ParticleType
-      // auto
-      particle = stack.AddParticle(
-          std::tuple<corsika::particles::Code, corsika::units::si::HEPEnergyType,
-                     corsika::stack::MomentumVector, corsika::geometry::Point,
-                     corsika::units::si::TimeType>{
-              particles::Code::Electron, 1.5_GeV,
-              stack::MomentumVector(dummyCS, {1_GeV, 1_GeV, 1_GeV}),
-              geometry::Point(dummyCS, {1 * meter, 1 * meter, 1 * meter}), 100_s});
-
+  setup::Stack::ParticleType particle = stack.AddParticle(
+      std::tuple<particles::Code, units::si::HEPEnergyType,
+                 corsika::stack::MomentumVector, geometry::Point, units::si::TimeType>{
+          particles::Code::Electron, 100_GeV,
+          corsika::stack::MomentumVector(dummyCS, {0_GeV, 0_GeV, -1_GeV}),
+          geometry::Point(dummyCS, {0_m, 0_m, 10_km}), 0_ns});
   SECTION("interface") {
 
     NullModel model(10_m);
diff --git a/Processes/Pythia/Decay.cc b/Processes/Pythia/Decay.cc
index 77241b106dff5d6f674f60ec9a2acfe763ca09be..222c68c8dd57d7fd57c453b62f53777e85ad062a 100644
--- a/Processes/Pythia/Decay.cc
+++ b/Processes/Pythia/Decay.cc
@@ -22,7 +22,8 @@ using std::vector;
 
 using namespace corsika;
 using namespace corsika::setup;
-using Particle = Stack::StackIterator; // ParticleType;
+using Projectile = corsika::setup::StackView::ParticleType;
+using Particle = corsika::setup::Stack::ParticleType;
 using Track = Trajectory;
 
 namespace corsika::process::pythia {
@@ -84,13 +85,13 @@ namespace corsika::process::pythia {
   }
 
   template <>
-  void Decay::DoDecay(Particle& p, Stack&) {
+  void Decay::DoDecay(Projectile& vP) {
     using geometry::Point;
     using namespace units;
     using namespace units::si;
 
-    auto const decayPoint = p.GetPosition();
-    auto const t0 = p.GetTime();
+    auto const decayPoint = vP.GetPosition();
+    auto const t0 = vP.GetTime();
 
     // coordinate system, get global frame of reference
     geometry::CoordinateSystem& rootCS =
@@ -103,17 +104,17 @@ namespace corsika::process::pythia {
     event.reset();
 
     // set particle unstable
-    Decay::SetUnstable(p.GetPID());
+    Decay::SetUnstable(vP.GetPID());
 
     // input particle PDG
-    auto const pdgCode = static_cast<int>(particles::GetPDG(p.GetPID()));
+    auto const pdgCode = static_cast<int>(particles::GetPDG(vP.GetPID()));
 
-    auto const pcomp = p.GetMomentum().GetComponents();
+    auto const pcomp = vP.GetMomentum().GetComponents();
     double px = pcomp[0] / 1_GeV;
     double py = pcomp[1] / 1_GeV;
     double pz = pcomp[2] / 1_GeV;
-    double en = p.GetEnergy() / 1_GeV;
-    double m = particles::GetMass(p.GetPID()) / 1_GeV;
+    double en = vP.GetEnergy() / 1_GeV;
+    double m = particles::GetMass(vP.GetPID()) / 1_GeV;
 
     // add particle to pythia stack
     event.append(pdgCode, 1, 0, 0, px, py, pz, en, m);
@@ -138,17 +139,17 @@ namespace corsika::process::pythia {
         cout << "particle: id=" << pyId << " momentum=" << pyP.GetComponents() / 1_GeV
              << " energy=" << pyEn << endl;
 
-        p.AddSecondary(
+        vP.AddSecondary(
             tuple<particles::Code, units::si::HEPEnergyType,
                   corsika::stack::MomentumVector, geometry::Point, units::si::TimeType>{
                 pyId, pyEn, pyP, decayPoint, t0});
       }
 
     // set particle stable
-    Decay::SetStable(p.GetPID());
+    Decay::SetStable(vP.GetPID());
 
     // remove original particle from corsika stack
-    p.Delete();
+    vP.Delete();
     //    if (fCount>10) throw std::runtime_error("stop here");
   }
 
diff --git a/Processes/Pythia/Decay.h b/Processes/Pythia/Decay.h
index fc76137160177afabe0d6624b2bc1b708f545ab4..6506625b07a04ec076919bafcbf0e8c92395aaf4 100644
--- a/Processes/Pythia/Decay.h
+++ b/Processes/Pythia/Decay.h
@@ -35,11 +35,11 @@ namespace corsika::process {
       void SetUnstable(const corsika::particles::Code);
       void SetStable(const corsika::particles::Code);
 
-      template <typename Particle>
-      corsika::units::si::TimeType GetLifetime(Particle const& p);
+      template <typename TParticle>
+      corsika::units::si::TimeType GetLifetime(TParticle const&);
 
-      template <typename Particle, typename Stack>
-      void DoDecay(Particle& p, Stack&);
+      template <typename TProjectile>
+      void DoDecay(TProjectile&);
 
     private:
       Pythia8::Pythia fPythia;
diff --git a/Processes/Pythia/Interaction.cc b/Processes/Pythia/Interaction.cc
index 66c445dd037b5987f10cf96b3e406d5dc8a8a04e..ae8104350086f5cfda94b174305d0f0366faa2ce 100644
--- a/Processes/Pythia/Interaction.cc
+++ b/Processes/Pythia/Interaction.cc
@@ -26,16 +26,14 @@ using std::tuple;
 
 using namespace corsika;
 using namespace corsika::setup;
-using Particle = Stack::StackIterator; // ParticleType;
+using Projectile = corsika::setup::StackView::ParticleType;
+using Particle = corsika::setup::Stack::ParticleType;
 using Track = Trajectory;
 
 namespace corsika::process::pythia {
 
   typedef corsika::geometry::Vector<corsika::units::si::hepmomentum_d> MomentumVector;
 
-  Interaction::Interaction(environment::Environment const& env)
-      : fEnvironment(env) {}
-
   Interaction::~Interaction() { cout << "Pythia::Interaction n=" << fCount << endl; }
 
   void Interaction::Init() {
@@ -78,7 +76,7 @@ namespace corsika::process::pythia {
   }
 
   void Interaction::SetParticleListStable(
-      const std::vector<particles::Code> particleList) {
+      std::vector<particles::Code> const& particleList) {
     for (auto p : particleList) Interaction::SetStable(p);
   }
 
@@ -213,8 +211,7 @@ namespace corsika::process::pythia {
         ideally as full particle object so that the four momenta
         and the boosts can be defined..
       */
-      const auto currentNode =
-          fEnvironment.GetUniverse()->GetContainingNode(p.GetPosition());
+      const auto* currentNode = p.GetNode();
       const auto mediumComposition =
           currentNode->GetModelProperties().GetNuclearComposition();
       // determine average interaction length
@@ -222,7 +219,7 @@ namespace corsika::process::pythia {
       int i = -1;
       si::CrossSectionType weightedProdCrossSection = 0_mb;
       // get weights of components from environment/medium
-      const auto w = mediumComposition.GetFractions();
+      const auto& w = mediumComposition.GetFractions();
       // loop over components in medium
       for (auto const targetId : mediumComposition.GetComponents()) {
         i++;
@@ -230,8 +227,7 @@ namespace corsika::process::pythia {
 
         auto const [productionCrossSection, elaCrossSection] =
             GetCrossSection(corsikaBeamId, targetId, ECoM);
-        [[maybe_unused]] auto elaCrossSectionCopy =
-            elaCrossSection; // ONLY TO AVOID COMPILER WARNING
+        [[maybe_unused]] const auto& dummy_elaCrossSection = elaCrossSection;
 
         cout << "Interaction: IntLength: pythia return (mb): "
              << productionCrossSection / 1_mb << endl
@@ -263,14 +259,14 @@ namespace corsika::process::pythia {
    */
 
   template <>
-  process::EProcessReturn Interaction::DoInteraction(Particle& p, Stack&) {
+  process::EProcessReturn Interaction::DoInteraction(Projectile& vP) {
 
     using namespace units;
     using namespace utl;
     using namespace units::si;
     using namespace geometry;
 
-    const auto corsikaBeamId = p.GetPID();
+    const auto corsikaBeamId = vP.GetPID();
     cout << "Pythia::Interaction: "
          << "DoInteraction: " << corsikaBeamId << " interaction? "
          << process::pythia::Interaction::CanInteract(corsikaBeamId) << endl;
@@ -286,8 +282,8 @@ namespace corsika::process::pythia {
           RootCoordinateSystem::GetInstance().GetRootCoordinateSystem();
 
       // position and time of interaction, not used in Sibyll
-      Point pOrig = p.GetPosition();
-      TimeType tOrig = p.GetTime();
+      Point pOrig = vP.GetPosition();
+      TimeType tOrig = vP.GetTime();
 
       // define target
       // FOR NOW: target is always at rest
@@ -296,8 +292,8 @@ namespace corsika::process::pythia {
       const FourVector PtargLab(eTargetLab, pTargetLab);
 
       // define projectile
-      HEPEnergyType const eProjectileLab = p.GetEnergy();
-      auto const pProjectileLab = p.GetMomentum();
+      HEPEnergyType const eProjectileLab = vP.GetEnergy();
+      auto const pProjectileLab = vP.GetMomentum();
 
       cout << "Interaction: ebeam lab: " << eProjectileLab / 1_GeV << endl
            << "Interaction: pbeam lab: " << pProjectileLab.GetComponents() / 1_GeV
@@ -332,12 +328,12 @@ namespace corsika::process::pythia {
       cout << "Interaction: time: " << tOrig << endl;
 
       HEPEnergyType Etot = eProjectileLab + eTargetLab;
-      MomentumVector Ptot = p.GetMomentum();
+      MomentumVector Ptot = vP.GetMomentum();
       // invariant mass, i.e. cm. energy
       HEPEnergyType Ecm = sqrt(Etot * Etot - Ptot.squaredNorm());
 
       // sample target mass number
-      const auto currentNode = fEnvironment.GetUniverse()->GetContainingNode(pOrig);
+      const auto* currentNode = vP.GetNode();
       const auto& mediumComposition =
           currentNode->GetModelProperties().GetNuclearComposition();
       // get cross sections for target materials
@@ -352,9 +348,8 @@ namespace corsika::process::pythia {
       for (size_t i = 0; i < compVec.size(); ++i) {
         auto const targetId = compVec[i];
         const auto [sigProd, sigEla] = GetCrossSection(corsikaBeamId, targetId, Ecm);
+        [[maybe_unused]] const auto& dummy_sigEla = sigEla;
         cross_section_of_components[i] = sigProd;
-        [[maybe_unused]] auto sigElaCopy =
-            sigEla; // to avoid not used warning in array binding
       }
 
       const auto corsikaTargetId =
@@ -392,19 +387,19 @@ namespace corsika::process::pythia {
         MomentumVector Plab_final(rootCS, {0.0_GeV, 0.0_GeV, 0.0_GeV});
         HEPEnergyType Elab_final = 0_GeV;
         for (int i = 0; i < event.size(); ++i) {
-          Pythia8::Particle& pp = event[i];
+          Pythia8::Particle& p8p = event[i];
           // skip particles that have decayed in pythia
-          if (!pp.isFinal()) continue;
+          if (!p8p.isFinal()) continue;
 
           auto const pyId =
-              particles::ConvertFromPDG(static_cast<particles::PDGCode>(pp.id()));
+              particles::ConvertFromPDG(static_cast<particles::PDGCode>(p8p.id()));
 
           const MomentumVector pyPlab(
-              rootCS, {pp.px() * 1_GeV, pp.py() * 1_GeV, pp.pz() * 1_GeV});
-          HEPEnergyType const pyEn = pp.e() * 1_GeV;
+              rootCS, {p8p.px() * 1_GeV, p8p.py() * 1_GeV, p8p.pz() * 1_GeV});
+          HEPEnergyType const pyEn = p8p.e() * 1_GeV;
 
           // add to corsika stack
-          auto pnew = p.AddSecondary(
+          auto pnew = vP.AddSecondary(
               tuple<particles::Code, units::si::HEPEnergyType, stack::MomentumVector,
                     geometry::Point, units::si::TimeType>{pyId, pyEn, pyPlab, pOrig,
                                                           tOrig});
@@ -417,7 +412,7 @@ namespace corsika::process::pythia {
              << ", Plab_final=" << (Plab_final / 1_GeV).GetComponents() << endl;
       }
       // delete current particle
-      p.Delete();
+      vP.Delete();
     }
     return process::EProcessReturn::eOk;
   }
diff --git a/Processes/Pythia/Interaction.h b/Processes/Pythia/Interaction.h
index 7476d09002c2015728cf164e0432f8a73e316026..ac27825acf0561d0d9e7e8e8b66961bdfc674e2f 100644
--- a/Processes/Pythia/Interaction.h
+++ b/Processes/Pythia/Interaction.h
@@ -19,10 +19,6 @@
 #include <corsika/units/PhysicalUnits.h>
 #include <tuple>
 
-namespace corsika::environment {
-  class Environment;
-}
-
 namespace corsika::process::pythia {
 
   class Interaction : public corsika::process::InteractionProcess<Interaction> {
@@ -31,12 +27,12 @@ namespace corsika::process::pythia {
     bool fInitialized = false;
 
   public:
-    Interaction(corsika::environment::Environment const& env);
+    Interaction() {}
     ~Interaction();
 
     void Init();
 
-    void SetParticleListStable(const std::vector<particles::Code>);
+    void SetParticleListStable(std::vector<particles::Code> const&);
     void SetUnstable(const corsika::particles::Code);
     void SetStable(const corsika::particles::Code);
 
@@ -55,19 +51,18 @@ namespace corsika::process::pythia {
                     const corsika::particles::Code TargetId,
                     const corsika::units::si::HEPEnergyType CoMenergy);
 
-    template <typename Particle, typename Track>
-    corsika::units::si::GrammageType GetInteractionLength(Particle&, Track&);
+    template <typename TParticle, typename TTrack>
+    corsika::units::si::GrammageType GetInteractionLength(TParticle&, TTrack&);
 
     /**
        In this function PYTHIA is called to produce one event. The
        event is copied (and boosted) into the shower lab frame.
      */
 
-    template <typename Particle, typename Stack>
-    corsika::process::EProcessReturn DoInteraction(Particle&, Stack&);
+    template <typename TProjctile>
+    corsika::process::EProcessReturn DoInteraction(TProjctile&);
 
   private:
-    corsika::environment::Environment const& fEnvironment;
     corsika::random::RNG& fRNG =
         corsika::random::RNGManager::GetInstance().GetRandomStream("pythia");
     Pythia8::Pythia fPythia;
diff --git a/Processes/Pythia/testPythia.cc b/Processes/Pythia/testPythia.cc
index a86e4de716cabe69e611ffd142c7065ad7bff40f..3fb2df13ecd1c24e674997a3c3aa468164f21d06 100644
--- a/Processes/Pythia/testPythia.cc
+++ b/Processes/Pythia/testPythia.cc
@@ -98,12 +98,15 @@ using namespace corsika::units::si;
 TEST_CASE("pythia process") {
 
   // setup environment, geometry
-  environment::Environment env;
+  environment::Environment<environment::IMediumModel> env;
   auto& universe = *(env.GetUniverse());
 
-  auto theMedium = environment::Environment::CreateNode<geometry::Sphere>(
-      geometry::Point{env.GetCoordinateSystem(), 0_m, 0_m, 0_m},
-      1_km * std::numeric_limits<double>::infinity());
+  geometry::CoordinateSystem const& cs = env.GetCoordinateSystem();
+
+  auto theMedium =
+      environment::Environment<environment::IMediumModel>::CreateNode<geometry::Sphere>(
+          geometry::Point{cs, 0_m, 0_m, 0_m},
+          1_km * std::numeric_limits<double>::infinity());
 
   using MyHomogeneousModel = environment::HomogeneousMedium<environment::IMediumModel>;
   theMedium->SetModelProperties<MyHomogeneousModel>(
@@ -112,10 +115,9 @@ TEST_CASE("pythia process") {
           std::vector<particles::Code>{particles::Code::Hydrogen},
           std::vector<float>{1.}));
 
+  auto const* nodePtr = theMedium.get(); // save the medium for later use before moving it
   universe.AddChild(std::move(theMedium));
 
-  const geometry::CoordinateSystem& cs = env.GetCoordinateSystem();
-
   geometry::Point const origin(cs, {0_m, 0_m, 0_m});
   geometry::Vector<units::si::SpeedType::dimension_type> v(cs, 0_m / second, 0_m / second,
                                                            1_m / second);
@@ -143,11 +145,12 @@ TEST_CASE("pythia process") {
 
     random::RNGManager::GetInstance().RegisterRandomStream("pythia");
 
-    process::pythia::Decay model(particleList);
+    corsika::stack::SecondaryView view(particle);
+    auto projectile = view.GetProjectile();
 
+    process::pythia::Decay model(particleList);
     model.Init();
-    /*[[maybe_unused]] const process::EProcessReturn ret =*/model.DoDecay(particle,
-                                                                          stack);
+    /*[[maybe_unused]] const process::EProcessReturn ret =*/model.DoDecay(projectile);
     [[maybe_unused]] const TimeType time = model.GetLifetime(particle);
   }
 
@@ -163,12 +166,13 @@ TEST_CASE("pythia process") {
         std::tuple<particles::Code, units::si::HEPEnergyType,
                    corsika::stack::MomentumVector, geometry::Point, units::si::TimeType>{
             particles::Code::PiPlus, E0, plab, pos, 0_ns});
+    particle.SetNode(nodePtr);
+    corsika::stack::SecondaryView view(particle);
+    auto projectile = view.GetProjectile();
 
-    process::pythia::Interaction model(env);
-
+    process::pythia::Interaction model;
     model.Init();
-    /*[[maybe_unused]] const process::EProcessReturn ret =*/model.DoInteraction(particle,
-                                                                                stack);
+    [[maybe_unused]] const process::EProcessReturn ret = model.DoInteraction(projectile);
     [[maybe_unused]] const GrammageType length =
         model.GetInteractionLength(particle, track);
   }
diff --git a/Processes/Sibyll/Interaction.cc b/Processes/Sibyll/Interaction.cc
index 83348508b37938b07eff8e664322e780930ba23c..ed550a012d63df6b89586198933ce10c4d01b8d2 100644
--- a/Processes/Sibyll/Interaction.cc
+++ b/Processes/Sibyll/Interaction.cc
@@ -53,7 +53,7 @@ namespace corsika::process::sibyll {
       if (fInternalDecays) {
         // define which particles are passed to corsika, i.e. which particles make it into
         // history even very shortlived particles like charm or pi0 are of interest here
-        const std::vector<particles::Code> HadronsWeWantTrackedByCorsika = {
+        const std::vector<particles::Code> hadronsWeWantTrackedByCorsika = {
             particles::Code::PiPlus,     particles::Code::PiMinus,
             particles::Code::Pi0,        particles::Code::KMinus,
             particles::Code::KPlus,      particles::Code::K0Long,
@@ -64,7 +64,7 @@ namespace corsika::process::sibyll {
             particles::Code::DMinus,     particles::Code::D0,
             particles::Code::D0Bar};
 
-        Interaction::SetParticleListStable(HadronsWeWantTrackedByCorsika);
+        Interaction::SetParticleListStable(hadronsWeWantTrackedByCorsika);
       }
 
       fInitialized = true;
@@ -72,7 +72,7 @@ namespace corsika::process::sibyll {
   }
 
   void Interaction::SetParticleListStable(
-      const std::vector<particles::Code> particleList) {
+      std::vector<particles::Code> const& particleList) {
     for (auto p : particleList) Interaction::SetStable(p);
   }
 
@@ -91,7 +91,7 @@ namespace corsika::process::sibyll {
   tuple<units::si::CrossSectionType, units::si::CrossSectionType>
   Interaction::GetCrossSection(const particles::Code BeamId,
                                const particles::Code TargetId,
-                               const units::si::HEPEnergyType CoMenergy) {
+                               const units::si::HEPEnergyType CoMenergy) const {
     using namespace units::si;
     double sigProd, sigEla, dummy, dum1, dum3, dum4;
     double dumdif[3];
@@ -118,7 +118,7 @@ namespace corsika::process::sibyll {
   }
 
   template <>
-  units::si::GrammageType Interaction::GetInteractionLength(Particle& p, Track&) {
+  units::si::GrammageType Interaction::GetInteractionLength(Particle& vP, Track&) const {
 
     using namespace units;
     using namespace units::si;
@@ -128,7 +128,7 @@ namespace corsika::process::sibyll {
     CoordinateSystem& rootCS =
         RootCoordinateSystem::GetInstance().GetRootCoordinateSystem();
 
-    const particles::Code corsikaBeamId = p.GetPID();
+    const particles::Code corsikaBeamId = vP.GetPID();
 
     // beam particles for sibyll : 1, 2, 3 for p, pi, k
     // read from cross section code table
@@ -138,9 +138,9 @@ namespace corsika::process::sibyll {
     MomentumVector pTarget(rootCS, {0_GeV, 0_GeV, 0_GeV});
 
     // total momentum and energy
-    HEPEnergyType Elab = p.GetEnergy() + constants::nucleonMass;
+    HEPEnergyType Elab = vP.GetEnergy() + constants::nucleonMass;
     MomentumVector pTotLab(rootCS, {0_GeV, 0_GeV, 0_GeV});
-    pTotLab += p.GetMomentum();
+    pTotLab += vP.GetMomentum();
     pTotLab += pTarget;
     auto const pTotLabNorm = pTotLab.norm();
     // calculate cm. energy
@@ -148,9 +148,9 @@ namespace corsika::process::sibyll {
         (Elab + pTotLabNorm) * (Elab - pTotLabNorm)); // binomial for numerical accuracy
 
     cout << "Interaction: LambdaInt: \n"
-         << " input energy: " << p.GetEnergy() / 1_GeV << endl
+         << " input energy: " << vP.GetEnergy() / 1_GeV << endl
          << " beam can interact:" << kInteraction << endl
-         << " beam pid:" << p.GetPID() << endl;
+         << " beam pid:" << vP.GetPID() << endl;
 
     // TODO: move limits into variables
     // FR: removed && Elab >= 8.5_GeV
@@ -162,7 +162,7 @@ namespace corsika::process::sibyll {
         ideally as full particle object so that the four momenta
         and the boosts can be defined..
       */
-      auto const* currentNode = p.GetNode();
+      auto const* currentNode = vP.GetNode();
       const auto mediumComposition =
           currentNode->GetModelProperties().GetNuclearComposition();
       // determine average interaction length
@@ -176,8 +176,9 @@ namespace corsika::process::sibyll {
         i++;
         cout << "Interaction: get interaction length for target: " << targetId << endl;
 
-        [[maybe_unused]] auto const [productionCrossSection, elaCrossSection] =
+        auto const [productionCrossSection, elaCrossSection] =
             GetCrossSection(corsikaBeamId, targetId, ECoM);
+        [[maybe_unused]] const auto& dummy_elaCX = elaCrossSection;
 
         cout << "Interaction: "
              << " IntLength: sibyll return (mb): " << productionCrossSection / 1_mb
@@ -208,14 +209,14 @@ namespace corsika::process::sibyll {
    */
 
   template <>
-  process::EProcessReturn Interaction::DoInteraction(Projectile& p) {
+  process::EProcessReturn Interaction::DoInteraction(Projectile& vP) {
 
     using namespace units;
     using namespace utl;
     using namespace units::si;
     using namespace geometry;
 
-    const auto corsikaBeamId = p.GetPID();
+    const auto corsikaBeamId = vP.GetPID();
     cout << "ProcessSibyll: "
          << "DoInteraction: " << corsikaBeamId << " interaction? "
          << process::sibyll::CanInteract(corsikaBeamId) << endl;
@@ -230,8 +231,8 @@ namespace corsika::process::sibyll {
           RootCoordinateSystem::GetInstance().GetRootCoordinateSystem();
 
       // position and time of interaction, not used in Sibyll
-      Point pOrig = p.GetPosition();
-      TimeType tOrig = p.GetTime();
+      Point pOrig = vP.GetPosition();
+      TimeType tOrig = vP.GetTime();
 
       // define target
       // for Sibyll is always a single nucleon
@@ -241,8 +242,8 @@ namespace corsika::process::sibyll {
       const FourVector PtargLab(eTargetLab, pTargetLab);
 
       // define projectile
-      HEPEnergyType const eProjectileLab = p.GetEnergy();
-      auto const pProjectileLab = p.GetMomentum();
+      HEPEnergyType const eProjectileLab = vP.GetEnergy();
+      auto const pProjectileLab = vP.GetMomentum();
 
       cout << "Interaction: ebeam lab: " << eProjectileLab / 1_GeV << endl
            << "Interaction: pbeam lab: " << pProjectileLab.GetComponents() / 1_GeV
@@ -277,12 +278,12 @@ namespace corsika::process::sibyll {
       cout << "Interaction: time: " << tOrig << endl;
 
       HEPEnergyType Etot = eProjectileLab + eTargetLab;
-      MomentumVector Ptot = p.GetMomentum();
+      MomentumVector Ptot = vP.GetMomentum();
       // invariant mass, i.e. cm. energy
       HEPEnergyType Ecm = sqrt(Etot * Etot - Ptot.squaredNorm());
 
       // sample target mass number
-      auto const* currentNode = p.GetNode();
+      auto const* currentNode = vP.GetNode();
       auto const& mediumComposition =
           currentNode->GetModelProperties().GetNuclearComposition();
       // get cross sections for target materials
@@ -296,8 +297,8 @@ namespace corsika::process::sibyll {
 
       for (size_t i = 0; i < compVec.size(); ++i) {
         auto const targetId = compVec[i];
-        [[maybe_unsused]] const auto [sigProd, sigEla] =
-            GetCrossSection(corsikaBeamId, targetId, Ecm);
+        const auto [sigProd, sigEla] = GetCrossSection(corsikaBeamId, targetId, Ecm);
+        [[maybe_unused]] const auto& dummy_sigEla = sigEla;
         cross_section_of_components[i] = sigProd;
       }
 
@@ -362,7 +363,7 @@ namespace corsika::process::sibyll {
           auto const Plab = boost.fromCoM(FourVector(eCoM, pCoM));
 
           // add to corsika stack
-          auto pnew = p.AddSecondary(
+          auto pnew = vP.AddSecondary(
               tuple<particles::Code, units::si::HEPEnergyType, stack::MomentumVector,
                     geometry::Point, units::si::TimeType>{
                   process::sibyll::ConvertFromSibyll(psib.GetPID()),
@@ -379,7 +380,7 @@ namespace corsika::process::sibyll {
       }
     }
     // delete current particle
-    p.Delete();
+    vP.Delete();
     return process::EProcessReturn::eOk;
   }
 
diff --git a/Processes/Sibyll/Interaction.h b/Processes/Sibyll/Interaction.h
index 4d70a0afb8bc53cb07c1ad09909bce103419dc47..4e1899f685e9254c3207850c227328340a051e94 100644
--- a/Processes/Sibyll/Interaction.h
+++ b/Processes/Sibyll/Interaction.h
@@ -32,18 +32,18 @@ namespace corsika::process::sibyll {
 
     void Init();
 
-    void SetParticleListStable(const std::vector<particles::Code>);
+    void SetParticleListStable(std::vector<particles::Code> const&);
     void SetUnstable(const corsika::particles::Code);
     void SetStable(const corsika::particles::Code);
 
     bool WasInitialized() { return fInitialized; }
-    bool IsValidCoMEnergy(corsika::units::si::HEPEnergyType ecm) {
+    bool IsValidCoMEnergy(corsika::units::si::HEPEnergyType ecm) const {
       return (fMinEnergyCoM <= ecm) && (ecm <= fMaxEnergyCoM);
     }
-    int GetMaxTargetMassNumber() { return fMaxTargetMassNumber; }
-    corsika::units::si::HEPEnergyType GetMinEnergyCoM() { return fMinEnergyCoM; }
-    corsika::units::si::HEPEnergyType GetMaxEnergyCoM() { return fMaxEnergyCoM; }
-    bool IsValidTarget(corsika::particles::Code TargetId) {
+    int GetMaxTargetMassNumber() const { return fMaxTargetMassNumber; }
+    corsika::units::si::HEPEnergyType GetMinEnergyCoM() const { return fMinEnergyCoM; }
+    corsika::units::si::HEPEnergyType GetMaxEnergyCoM() const { return fMaxEnergyCoM; }
+    bool IsValidTarget(corsika::particles::Code TargetId) const {
       return (corsika::particles::GetNucleusA(TargetId) < fMaxTargetMassNumber) &&
              corsika::particles::IsNucleus(TargetId);
     }
@@ -51,18 +51,18 @@ namespace corsika::process::sibyll {
     std::tuple<corsika::units::si::CrossSectionType, corsika::units::si::CrossSectionType>
     GetCrossSection(const corsika::particles::Code BeamId,
                     const corsika::particles::Code TargetId,
-                    const corsika::units::si::HEPEnergyType CoMenergy);
+                    const corsika::units::si::HEPEnergyType CoMenergy) const;
 
     template <typename Particle, typename Track>
-    corsika::units::si::GrammageType GetInteractionLength(Particle&, Track&);
+    corsika::units::si::GrammageType GetInteractionLength(Particle&, Track&) const;
 
     /**
        In this function SIBYLL is called to produce one event. The
        event is copied (and boosted) into the shower lab frame.
      */
 
-    template <typename Particle>
-    corsika::process::EProcessReturn DoInteraction(Particle&);
+    template <typename TProjectile>
+    corsika::process::EProcessReturn DoInteraction(TProjectile&);
 
   private:
     corsika::random::RNG& fRNG =
diff --git a/Processes/Sibyll/NuclearInteraction.cc b/Processes/Sibyll/NuclearInteraction.cc
index da85b0f3da83729de49e21d921fce068b4990cea..31abd9da350e1c80c24868eb2313e860b51bd821 100644
--- a/Processes/Sibyll/NuclearInteraction.cc
+++ b/Processes/Sibyll/NuclearInteraction.cc
@@ -37,37 +37,42 @@ using Track = Trajectory;
 
 namespace corsika::process::sibyll {
 
-  NuclearInteraction::NuclearInteraction(process::sibyll::Interaction& hadint)
-      : fHadronicInteraction(hadint) {}
+  template <>
+  NuclearInteraction<SetupEnvironment>::NuclearInteraction(
+      process::sibyll::Interaction& hadint, SetupEnvironment const& env)
+      : fEnvironment(env)
+      , fHadronicInteraction(hadint) {}
 
-  NuclearInteraction::~NuclearInteraction() {
+  template <>
+  NuclearInteraction<SetupEnvironment>::~NuclearInteraction() {
     cout << "Nuclib::NuclearInteraction n=" << fCount << " Nnuc=" << fNucCount << endl;
-    fTargetComponentsIndex.clear();
   }
 
-  void NuclearInteraction::Init() {
-
-    using random::RNGManager;
-
-    // initialize hadronic interaction module
-    // TODO: safe to run multiple initializations?
-    if (!fHadronicInteraction.WasInitialized()) fHadronicInteraction.Init();
-
-    // check compatibility of energy ranges, someone could try to use low-energy model..
-    if (!fHadronicInteraction.IsValidCoMEnergy(GetMinEnergyPerNucleonCoM()) ||
-        !fHadronicInteraction.IsValidCoMEnergy(GetMaxEnergyPerNucleonCoM()))
-      throw std::runtime_error(
-          "NuclearInteraction: hadronic interaction model incompatible!");
-
-    // initialize nuclib
-    // TODO: make sure this does not overlap with sibyll
-    nuc_nuc_ini_();
+  template <>
+  void NuclearInteraction<SetupEnvironment>::PrintCrossSectionTable(
+      corsika::particles::Code pCode) {
+    using namespace corsika::particles;
+    const int k = fTargetComponentsIndex.at(pCode);
+    Code pNuclei[] = {Code::Helium, Code::Lithium7, Code::Oxygen,
+                      Code::Neon,   Code::Argon,    Code::Iron};
+    cout << "en/A ";
+    for (auto& j : pNuclei) cout << std::setw(9) << j;
+    cout << endl;
 
-    // initialize cross sections
-    InitializeNuclearCrossSections();
+    // loop over energy bins
+    for (int i = 0; i < GetNEnergyBins(); ++i) {
+      cout << " " << i << "  ";
+      for (auto& n : pNuclei) {
+        auto const j = GetNucleusA(n);
+        cout << " " << std::setprecision(5) << std::setw(8)
+             << cnucsignuc_.sigma[j - 1][k][i];
+      }
+      cout << endl;
+    }
   }
 
-  void NuclearInteraction::InitializeNuclearCrossSections() {
+  template <>
+  void NuclearInteraction<SetupEnvironment>::InitializeNuclearCrossSections() {
     using namespace corsika::particles;
     using namespace units::si;
 
@@ -76,9 +81,9 @@ namespace corsika::process::sibyll {
     auto const allElementsInUniverse = std::invoke([&]() {
       std::set<particles::Code> allElementsInUniverse;
       auto collectElements = [&](auto& vtn) {
-        if (auto const mp = vtn.GetModelPropertiesPtr();
-            mp != nullptr) { // do not query Universe it self, it has no ModelProperties
-          auto const& comp = mp->GetNuclearComposition().GetComponents();
+        if (vtn.HasModelProperties()) {
+          auto const& comp =
+              vtn.GetModelProperties().GetNuclearComposition().GetComponents();
           for (auto const c : comp) allElementsInUniverse.insert(c);
         }
       };
@@ -113,10 +118,10 @@ namespace corsika::process::sibyll {
         const double dsig = siginel / 1_mb;
         const double dsigela = sigela / 1_mb;
         // loop over projectiles, mass numbers from 2 to fMaxNucleusAProjectile
-        for (int j = 1; j < fMaxNucleusAProjectile; ++j) {
+        for (int j = 1; j < gMaxNucleusAProjectile; ++j) {
           const int jj = j + 1;
           double sig_out, dsig_out, sigqe_out, dsigqe_out;
-          sigma_mc_(jj, ib, dsig, dsigela, fNSample, sig_out, dsig_out, sigqe_out,
+          sigma_mc_(jj, ib, dsig, dsigela, gNSample, sig_out, dsig_out, sigqe_out,
                     dsigqe_out);
           // write to table
           cnucsignuc_.sigma[j][k][i] = sig_out;
@@ -132,28 +137,28 @@ namespace corsika::process::sibyll {
     }
   }
 
-  void NuclearInteraction::PrintCrossSectionTable(corsika::particles::Code pCode) {
-    using namespace corsika::particles;
-    const int k = fTargetComponentsIndex.at(pCode);
-    Code pNuclei[] = {Code::Helium, Code::Lithium7, Code::Oxygen,
-                      Code::Neon,   Code::Argon,    Code::Iron};
-    cout << "en/A ";
-    for (auto& j : pNuclei) cout << std::setw(9) << j;
-    cout << endl;
+  template <>
+  void NuclearInteraction<SetupEnvironment>::Init() {
+    // initialize hadronic interaction module
+    // TODO: safe to run multiple initializations?
+    if (!fHadronicInteraction.WasInitialized()) fHadronicInteraction.Init();
 
-    // loop over energy bins
-    for (int i = 0; i < GetNEnergyBins(); ++i) {
-      cout << " " << i << "  ";
-      for (auto& n : pNuclei) {
-        auto const j = GetNucleusA(n);
-        cout << " " << std::setprecision(5) << std::setw(8)
-             << cnucsignuc_.sigma[j - 1][k][i];
-      }
-      cout << endl;
-    }
+    // check compatibility of energy ranges, someone could try to use low-energy model..
+    if (!fHadronicInteraction.IsValidCoMEnergy(GetMinEnergyPerNucleonCoM()) ||
+        !fHadronicInteraction.IsValidCoMEnergy(GetMaxEnergyPerNucleonCoM()))
+      throw std::runtime_error(
+          "NuclearInteraction: hadronic interaction model incompatible!");
+
+    // initialize nuclib
+    // TODO: make sure this does not overlap with sibyll
+    nuc_nuc_ini_();
+
+    // initialize cross sections
+    InitializeNuclearCrossSections();
   }
 
-  units::si::CrossSectionType NuclearInteraction::ReadCrossSectionTable(
+  template <>
+  units::si::CrossSectionType NuclearInteraction<SetupEnvironment>::ReadCrossSectionTable(
       const int ia, particles::Code pTarget, units::si::HEPEnergyType elabnuc) {
     using namespace corsika::particles;
     using namespace units::si;
@@ -171,15 +176,17 @@ namespace corsika::process::sibyll {
 
   // TODO: remove elastic cross section?
   template <>
+  template <>
   tuple<units::si::CrossSectionType, units::si::CrossSectionType>
-  NuclearInteraction::GetCrossSection(Particle& p, const particles::Code TargetId) {
+  NuclearInteraction<SetupEnvironment>::GetCrossSection(Particle& vP,
+                                                        const particles::Code TargetId) {
     using namespace units::si;
-    if (p.GetPID() != particles::Code::Nucleus)
+    if (vP.GetPID() != particles::Code::Nucleus)
       throw std::runtime_error(
           "NuclearInteraction: GetCrossSection: particle not a nucleus!");
 
-    auto const iBeamA = p.GetNuclearA();
-    HEPEnergyType LabEnergyPerNuc = p.GetEnergy() / iBeamA;
+    auto const iBeamA = vP.GetNuclearA();
+    HEPEnergyType LabEnergyPerNuc = vP.GetEnergy() / iBeamA;
     cout << "NuclearInteraction: GetCrossSection: called with: beamNuclA= " << iBeamA
          << " TargetId= " << TargetId << " LabEnergyPerNuc= " << LabEnergyPerNuc / 1_GeV
          << endl;
@@ -208,7 +215,9 @@ namespace corsika::process::sibyll {
   }
 
   template <>
-  units::si::GrammageType NuclearInteraction::GetInteractionLength(Particle& p, Track&) {
+  template <>
+  units::si::GrammageType NuclearInteraction<SetupEnvironment>::GetInteractionLength(
+      Particle& vP, Track&) {
 
     using namespace units;
     using namespace units::si;
@@ -218,7 +227,7 @@ namespace corsika::process::sibyll {
     CoordinateSystem& rootCS =
         RootCoordinateSystem::GetInstance().GetRootCoordinateSystem();
 
-    const particles::Code corsikaBeamId = p.GetPID();
+    const particles::Code corsikaBeamId = vP.GetPID();
     if (!particles::IsNucleus(corsikaBeamId)) {
       // no nuclear interaction
       return std::numeric_limits<double>::infinity() * 1_g / (1_cm * 1_cm);
@@ -235,12 +244,12 @@ namespace corsika::process::sibyll {
     corsika::stack::MomentumVector pTarget(rootCS, {0.0_GeV, 0.0_GeV, 0.0_GeV});
 
     // total momentum and energy
-    HEPEnergyType Elab = p.GetEnergy() + constants::nucleonMass;
-    int const nuclA = p.GetNuclearA();
-    auto const ElabNuc = p.GetEnergy() / nuclA;
+    HEPEnergyType Elab = vP.GetEnergy() + constants::nucleonMass;
+    int const nuclA = vP.GetNuclearA();
+    auto const ElabNuc = vP.GetEnergy() / nuclA;
 
     corsika::stack::MomentumVector pTotLab(rootCS, {0.0_GeV, 0.0_GeV, 0.0_GeV});
-    pTotLab += p.GetMomentum();
+    pTotLab += vP.GetMomentum();
     pTotLab += pTarget;
     auto const pTotLabNorm = pTotLab.norm();
     // calculate cm. energy
@@ -258,8 +267,8 @@ namespace corsika::process::sibyll {
 
     // energy limits
     // TODO: values depend on hadronic interaction model !! this is sibyll specific
-    if (ElabNuc >= 8.5_GeV && ECoMNN >= fMinEnergyPerNucleonCoM &&
-        ECoMNN < fMaxEnergyPerNucleonCoM) {
+    if (ElabNuc >= 8.5_GeV && ECoMNN >= gMinEnergyPerNucleonCoM &&
+        ECoMNN < gMaxEnergyPerNucleonCoM) {
 
       // get target from environment
       /*
@@ -267,7 +276,7 @@ namespace corsika::process::sibyll {
         ideally as full particle object so that the four momenta
         and the boosts can be defined..
       */
-      auto const* const currentNode = p.GetNode();
+      auto const* const currentNode = vP.GetNode();
       auto const& mediumComposition =
           currentNode->GetModelProperties().GetNuclearComposition();
       // determine average interaction length
@@ -275,15 +284,15 @@ namespace corsika::process::sibyll {
       int i = -1;
       si::CrossSectionType weightedProdCrossSection = 0_mb;
       // get weights of components from environment/medium
-      const auto w = mediumComposition.GetFractions();
+      const auto& w = mediumComposition.GetFractions();
       // loop over components in medium
       for (auto const targetId : mediumComposition.GetComponents()) {
         i++;
         cout << "NuclearInteraction: get interaction length for target: " << targetId
              << endl;
         auto const [productionCrossSection, elaCrossSection] =
-            GetCrossSection(p, targetId);
-        [[maybe_unused]] auto elaCrossSectionCopy = elaCrossSection;
+            GetCrossSection(vP, targetId);
+        [[maybe_unused]] auto& dummy_elaCrossSection = elaCrossSection;
 
         cout << "NuclearInteraction: "
              << "IntLength: nuclib return (mb): " << productionCrossSection / 1_mb
@@ -298,7 +307,7 @@ namespace corsika::process::sibyll {
       GrammageType const int_length = mediumComposition.GetAverageMassNumber() *
                                       units::constants::u / weightedProdCrossSection;
       cout << "NuclearInteraction: "
-           << "interaction length (g/cm2): " << int_length / (0.001_kg) * 1_cm * 1_cm
+           << "interaction length (g/cm2): " << int_length * (1_cm * 1_cm / (0.001_kg))
            << endl;
 
       return int_length;
@@ -308,7 +317,9 @@ namespace corsika::process::sibyll {
   }
 
   template <>
-  process::EProcessReturn NuclearInteraction::DoInteraction(Projectile& p) {
+  template <>
+  process::EProcessReturn NuclearInteraction<SetupEnvironment>::DoInteraction(
+      Projectile& vP) {
 
     // this routine superimposes different nucleon-nucleon interactions
     // in a nucleus-nucleus interaction, based the SIBYLL routine SIBNUC
@@ -318,9 +329,9 @@ namespace corsika::process::sibyll {
     using namespace units::si;
     using namespace geometry;
 
-    const auto ProjId = p.GetPID();
+    const auto ProjId = vP.GetPID();
     // TODO: calculate projectile mass in nuclearStackExtension
-    //      const auto ProjMass = p.GetMass();
+    //      const auto ProjMass = vP.GetMass();
     cout << "NuclearInteraction: DoInteraction: called with:" << ProjId << endl;
 
     if (!IsNucleus(ProjId)) {
@@ -337,8 +348,8 @@ namespace corsika::process::sibyll {
           "should use NuclearStackExtension!");
 
     auto const ProjMass =
-        p.GetNuclearZ() * particles::Proton::GetMass() +
-        (p.GetNuclearA() - p.GetNuclearZ()) * particles::Neutron::GetMass();
+        vP.GetNuclearZ() * particles::Proton::GetMass() +
+        (vP.GetNuclearA() - vP.GetNuclearZ()) * particles::Neutron::GetMass();
     cout << "NuclearInteraction: projectile mass: " << ProjMass / 1_GeV << endl;
 
     fCount++;
@@ -347,21 +358,21 @@ namespace corsika::process::sibyll {
         RootCoordinateSystem::GetInstance().GetRootCoordinateSystem();
 
     // position and time of interaction, not used in NUCLIB
-    Point pOrig = p.GetPosition();
-    TimeType tOrig = p.GetTime();
+    Point pOrig = vP.GetPosition();
+    TimeType tOrig = vP.GetTime();
 
     cout << "Interaction: position of interaction: " << pOrig.GetCoordinates() << endl;
     cout << "Interaction: time: " << tOrig << endl;
 
     // projectile nucleon number
-    const int kAProj = p.GetNuclearA(); // GetNucleusA(ProjId);
+    const int kAProj = vP.GetNuclearA(); // GetNucleusA(ProjId);
     if (kAProj > GetMaxNucleusAProjectile())
       throw std::runtime_error("Projectile nucleus too large for NUCLIB!");
 
     // kinematics
     // define projectile nucleus
-    HEPEnergyType const eProjectileLab = p.GetEnergy();
-    auto const pProjectileLab = p.GetMomentum();
+    HEPEnergyType const eProjectileLab = vP.GetEnergy();
+    auto const pProjectileLab = vP.GetMomentum();
     const FourVector PprojLab(eProjectileLab, pProjectileLab);
 
     cout << "NuclearInteraction: eProj lab: " << eProjectileLab / 1_GeV << endl
@@ -369,8 +380,8 @@ namespace corsika::process::sibyll {
          << endl;
 
     // define projectile nucleon
-    HEPEnergyType const eProjectileNucLab = p.GetEnergy() / kAProj;
-    auto const pProjectileNucLab = p.GetMomentum() / kAProj;
+    HEPEnergyType const eProjectileNucLab = vP.GetEnergy() / kAProj;
+    auto const pProjectileNucLab = vP.GetMomentum() / kAProj;
     const FourVector PprojNucLab(eProjectileNucLab, pProjectileNucLab);
 
     cout << "NuclearInteraction: eProjNucleon lab: " << eProjectileNucLab / 1_GeV << endl
@@ -422,7 +433,7 @@ namespace corsika::process::sibyll {
     //
     // proton stand-in for nucleon
     const auto beamId = particles::Proton::GetCode();
-    auto const* const currentNode = p.GetNode();
+    auto const* const currentNode = vP.GetNode();
     const auto& mediumComposition =
         currentNode->GetModelProperties().GetNuclearComposition();
     cout << "get nucleon-nucleus cross sections for target materials.." << endl;
@@ -547,15 +558,16 @@ namespace corsika::process::sibyll {
 
       if (nuclA == 1)
         // add nucleon
-        p.AddSecondary(tuple<particles::Code, units::si::HEPEnergyType,
-                             stack::MomentumVector, geometry::Point, units::si::TimeType>{
-            specCode, Plab.GetTimeLikeComponent(), Plab.GetSpaceLikeComponents(), pOrig,
-            tOrig});
+        vP.AddSecondary(
+            tuple<particles::Code, units::si::HEPEnergyType, stack::MomentumVector,
+                  geometry::Point, units::si::TimeType>{
+                specCode, Plab.GetTimeLikeComponent(), Plab.GetSpaceLikeComponents(),
+                pOrig, tOrig});
       else
         // add nucleus
-        p.AddSecondary(tuple<particles::Code, units::si::HEPEnergyType,
-                             corsika::stack::MomentumVector, geometry::Point,
-                             units::si::TimeType, unsigned short, unsigned short>{
+        vP.AddSecondary(tuple<particles::Code, units::si::HEPEnergyType,
+                              corsika::stack::MomentumVector, geometry::Point,
+                              units::si::TimeType, unsigned short, unsigned short>{
             specCode, Plab.GetTimeLikeComponent(), Plab.GetSpaceLikeComponents(), pOrig,
             tOrig, nuclA, nuclZ});
     }
@@ -574,7 +586,7 @@ namespace corsika::process::sibyll {
       const double mass_ratio = particles::GetMass(elaNucCode) / ProjMass;
       auto const Plab = PprojLab * mass_ratio;
 
-      p.AddSecondary(
+      vP.AddSecondary(
           tuple<particles::Code, units::si::HEPEnergyType, corsika::stack::MomentumVector,
                 geometry::Point, units::si::TimeType>{
               elaNucCode, Plab.GetTimeLikeComponent(), Plab.GetSpaceLikeComponents(),
@@ -588,7 +600,7 @@ namespace corsika::process::sibyll {
       auto pCode = particles::Proton::GetCode();
       // temporarily add to stack, will be removed after interaction in DoInteraction
       cout << "inelastic interaction no. " << j << endl;
-      auto inelasticNucleon = p.AddSecondary(
+      auto inelasticNucleon = vP.AddSecondary(
           tuple<particles::Code, units::si::HEPEnergyType, corsika::stack::MomentumVector,
                 geometry::Point, units::si::TimeType>{
               pCode, PprojNucLab.GetTimeLikeComponent(),
diff --git a/Processes/Sibyll/NuclearInteraction.h b/Processes/Sibyll/NuclearInteraction.h
index 520265fbb692a34571f5e8baa23de3d5e9c4372e..6bee9ba7a7964e74112c2bf60e5cbd4b1c23c2fa 100644
--- a/Processes/Sibyll/NuclearInteraction.h
+++ b/Processes/Sibyll/NuclearInteraction.h
@@ -24,15 +24,15 @@ namespace corsika::process::sibyll {
    *
    *
    **/
-
+  template <class TEnvironment>
   class NuclearInteraction
-      : public corsika::process::InteractionProcess<NuclearInteraction> {
+      : public corsika::process::InteractionProcess<NuclearInteraction<TEnvironment>> {
 
     int fCount = 0;
     int fNucCount = 0;
 
   public:
-    NuclearInteraction(corsika::process::sibyll::Interaction& hadint);
+    NuclearInteraction(corsika::process::sibyll::Interaction&, TEnvironment const&);
     ~NuclearInteraction();
     void Init();
     void InitializeNuclearCrossSections();
@@ -40,38 +40,41 @@ namespace corsika::process::sibyll {
     corsika::units::si::CrossSectionType ReadCrossSectionTable(
         const int, corsika::particles::Code, corsika::units::si::HEPEnergyType);
     corsika::units::si::HEPEnergyType GetMinEnergyPerNucleonCoM() {
-      return fMinEnergyPerNucleonCoM;
+      return gMinEnergyPerNucleonCoM;
     }
     corsika::units::si::HEPEnergyType GetMaxEnergyPerNucleonCoM() {
-      return fMaxEnergyPerNucleonCoM;
+      return gMaxEnergyPerNucleonCoM;
     }
-    int GetMaxNucleusAProjectile() { return fMaxNucleusAProjectile; }
-    int GetMaxNFragments() { return fMaxNFragments; }
-    int GetNEnergyBins() { return fNEnBins; }
+    int constexpr GetMaxNucleusAProjectile() { return gMaxNucleusAProjectile; }
+    int constexpr GetMaxNFragments() { return gMaxNFragments; }
+    int constexpr GetNEnergyBins() { return gNEnBins; }
+
     template <typename Particle>
     std::tuple<corsika::units::si::CrossSectionType, corsika::units::si::CrossSectionType>
     GetCrossSection(Particle& p, const corsika::particles::Code TargetId);
 
     template <typename Particle, typename Track>
-    corsika::units::si::GrammageType GetInteractionLength(Particle& p, Track&);
+    corsika::units::si::GrammageType GetInteractionLength(Particle&, Track&);
 
     template <typename Projectle>
-    corsika::process::EProcessReturn DoInteraction(Projectle& p);
+    corsika::process::EProcessReturn DoInteraction(Projectle&);
 
   private:
+    TEnvironment const& fEnvironment;
     corsika::process::sibyll::Interaction& fHadronicInteraction;
     std::map<corsika::particles::Code, int> fTargetComponentsIndex;
     corsika::random::RNG& fRNG =
         corsika::random::RNGManager::GetInstance().GetRandomStream("s_rndm");
-    const int fNSample = 500; // number of samples in MC estimation of cross section
-    const int fMaxNucleusAProjectile = 56;
-    const int fNEnBins = 6;
-    const int fMaxNFragments = 60;
+    static constexpr int gNSample =
+        500; // number of samples in MC estimation of cross section
+    static constexpr int gMaxNucleusAProjectile = 56;
+    static constexpr int gNEnBins = 6;
+    static constexpr int gMaxNFragments = 60;
     // energy limits defined by table used for cross section in signuc.f
     // 10**1 GeV to 10**6 GeV
-    const corsika::units::si::HEPEnergyType fMinEnergyPerNucleonCoM =
+    static constexpr corsika::units::si::HEPEnergyType gMinEnergyPerNucleonCoM =
         10. * 1e9 * corsika::units::si::electronvolt;
-    const corsika::units::si::HEPEnergyType fMaxEnergyPerNucleonCoM =
+    static constexpr corsika::units::si::HEPEnergyType gMaxEnergyPerNucleonCoM =
         1.e6 * 1e9 * corsika::units::si::electronvolt;
   };
 
diff --git a/Processes/Sibyll/testSibyll.cc b/Processes/Sibyll/testSibyll.cc
index ce096994b7829547f28e5f88bf53ff623108daab..d5f5d9bc8e39ac775de3fb9d541a18b596941bad 100644
--- a/Processes/Sibyll/testSibyll.cc
+++ b/Processes/Sibyll/testSibyll.cc
@@ -119,7 +119,7 @@ TEST_CASE("SibyllInterface", "[processes]") {
                    corsika::stack::MomentumVector, geometry::Point, units::si::TimeType>{
             particles::Code::Proton, E0, plab, pos, 0_ns});
     particle.SetNode(nodePtr);
-    stack::SecondaryView view(particle);
+    corsika::stack::SecondaryView view(particle);
     auto projectile = view.GetProjectile();
 
     Interaction model;
@@ -145,11 +145,11 @@ TEST_CASE("SibyllInterface", "[processes]") {
                                      units::si::TimeType, unsigned short, unsigned short>{
             particles::Code::Nucleus, E0, plab, pos, 0_ns, 4, 2});
     particle.SetNode(nodePtr);
-    stack::SecondaryView view(particle);
+    corsika::stack::SecondaryView view(particle);
     auto projectile = view.GetProjectile();
 
     Interaction hmodel;
-    NuclearInteraction model(hmodel);
+    NuclearInteraction model(hmodel, env);
 
     model.Init();
     [[maybe_unused]] const process::EProcessReturn ret = model.DoInteraction(projectile);
@@ -169,7 +169,7 @@ TEST_CASE("SibyllInterface", "[processes]") {
         std::tuple<particles::Code, units::si::HEPEnergyType,
                    corsika::stack::MomentumVector, geometry::Point, units::si::TimeType>{
             particles::Code::Proton, E0, plab, pos, 0_ns});
-    stack::SecondaryView view(particle);
+    corsika::stack::SecondaryView view(particle);
     auto projectile = view.GetProjectile();
 
     const std::vector<particles::Code> particleList = {
diff --git a/Processes/StackInspector/CMakeLists.txt b/Processes/StackInspector/CMakeLists.txt
index f00f44c2ab6b5513630f5344545f988b8e78dc3f..f8297639672f215e7a34e2330bd8e8387454d185 100644
--- a/Processes/StackInspector/CMakeLists.txt
+++ b/Processes/StackInspector/CMakeLists.txt
@@ -57,7 +57,6 @@ add_executable (testStackInspector testStackInspector.cc)
 target_link_libraries (
   testStackInspector
   ProcessStackInspector
-  CORSIKAsetup
   CORSIKAgeometry
   CORSIKAunits
   CORSIKAthirdparty # for catch2
diff --git a/Processes/StackInspector/StackInspector.cc b/Processes/StackInspector/StackInspector.cc
index eb0c9e11f871dfc22f5b2a27f46ef8f0e6051d3d..f192926ca73fa2032d05204a80a9250317504f9b 100644
--- a/Processes/StackInspector/StackInspector.cc
+++ b/Processes/StackInspector/StackInspector.cc
@@ -16,7 +16,6 @@
 
 #include <corsika/logging/Logger.h>
 
-#include <corsika/cascade/testCascade.h>
 #include <corsika/setup/SetupTrajectory.h>
 
 #include <iostream>
@@ -37,14 +36,12 @@ template <typename Stack>
 StackInspector<Stack>::~StackInspector() {}
 
 template <typename Stack>
-process::EProcessReturn StackInspector<Stack>::DoContinuous(Particle&,
-                                                            setup::Trajectory&) {
-
+process::EProcessReturn StackInspector<Stack>::DoStack(Stack& vS) {
   if (!fReport) return process::EProcessReturn::eOk;
   [[maybe_unused]] int i = 0;
   HEPEnergyType Etot = 0_GeV;
 
-  for (auto& iterP : s) {
+  for (auto& iterP : vS) {
     HEPEnergyType E = iterP.GetEnergy();
     Etot += E;
     geometry::CoordinateSystem& rootCS = geometry::RootCoordinateSystem::GetInstance()
@@ -53,27 +50,21 @@ process::EProcessReturn StackInspector<Stack>::DoContinuous(Particle&,
     cout << "StackInspector: i=" << setw(5) << fixed << (i++) << ", id=" << setw(30)
          << iterP.GetPID() << " E=" << setw(15) << scientific << (E / 1_GeV) << " GeV, "
          << " pos=" << pos << " node = " << iterP.GetNode();
-    // if (iterP.GetPID()==Code::Nucleus)
-    // cout << " nuc_ref=" << iterP.GetNucleusRef();
+    if (iterP.GetPID() == Code::Nucleus) cout << " nuc_ref=" << iterP.GetNucleusRef();
     cout << endl;
   }
   fCountStep++;
-  cout << "StackInspector: nStep=" << fCountStep << " stackSize=" << s.GetSize()
+  cout << "StackInspector: nStep=" << fCountStep << " stackSize=" << vS.GetSize()
        << " Estack=" << Etot / 1_GeV << " GeV" << endl;
   return process::EProcessReturn::eOk;
 }
 
-template <typename Stack>
-corsika::units::si::LengthType StackInspector<Stack>::MaxStepLength(Particle&,
-                                                                    setup::Trajectory&) {
-  return std::numeric_limits<double>::infinity() * meter;
-}
-
 template <typename Stack>
 void StackInspector<Stack>::Init() {
   fCountStep = 0;
 }
 
+#include <corsika/cascade/testCascade.h>
 #include <corsika/setup/SetupStack.h>
 
 template class process::stack_inspector::StackInspector<setup::Stack>;
diff --git a/Processes/StackInspector/StackInspector.h b/Processes/StackInspector/StackInspector.h
index c4262c1754ddb66cdd55ddc3689e507541da7a7c..4674a591bd1a0ecec1adf5cf80030dd8d79b91a8 100644
--- a/Processes/StackInspector/StackInspector.h
+++ b/Processes/StackInspector/StackInspector.h
@@ -12,7 +12,7 @@
 #ifndef _Physics_StackInspector_StackInspector_h_
 #define _Physics_StackInspector_StackInspector_h_
 
-#include <corsika/process/ContinuousProcess.h>
+#include <corsika/process/StackProcess.h>
 #include <corsika/setup/SetupTrajectory.h>
 #include <corsika/units/PhysicalUnits.h>
 
@@ -21,8 +21,7 @@ namespace corsika::process {
   namespace stack_inspector {
 
     template <typename Stack>
-    class StackInspector
-        : public corsika::process::ContinuousProcess<StackInspector<Stack>> {
+    class StackInspector : public corsika::process::StackProcess<StackInspector<Stack>> {
 
       typedef typename Stack::ParticleType Particle;
 
@@ -31,9 +30,7 @@ namespace corsika::process {
       ~StackInspector();
 
       void Init();
-      EProcessReturn DoContinuous(Particle&, corsika::setup::Trajectory&);
-      corsika::units::si::LengthType MaxStepLength(Particle&,
-                                                   corsika::setup::Trajectory&);
+      EProcessReturn DoStack(Stack&);
 
     private:
       bool fReport;
diff --git a/Processes/StackInspector/testStackInspector.cc b/Processes/StackInspector/testStackInspector.cc
index 11e9cff3e4eae58513694dd3b64ba6a6ea64bead..d1cc10739c09102d7138a69ba06528fa503ea81b 100644
--- a/Processes/StackInspector/testStackInspector.cc
+++ b/Processes/StackInspector/testStackInspector.cc
@@ -21,12 +21,12 @@
 
 #include <corsika/units/PhysicalUnits.h>
 
-#include <corsika/setup/SetupStack.h>
-#include <corsika/setup/SetupTrajectory.h>
+#include <corsika/cascade/testCascade.h>
 
 using namespace corsika::units::si;
 using namespace corsika::process::stack_inspector;
 using namespace corsika;
+using namespace corsika::geometry;
 
 TEST_CASE("StackInspector", "[processes]") {
 
@@ -38,21 +38,21 @@ TEST_CASE("StackInspector", "[processes]") {
   geometry::Line line(origin, v);
   geometry::Trajectory<geometry::Line> track(line, 10_s);
 
-  setup::Stack stack;
-  auto particle = stack.AddParticle(
+  TestCascadeStack stack;
+  stack.Clear();
+  HEPEnergyType E0 = 100_GeV;
+  stack.AddParticle(
       std::tuple<particles::Code, units::si::HEPEnergyType,
                  corsika::stack::MomentumVector, geometry::Point, units::si::TimeType>{
-          particles::Code::Electron, 10_GeV,
+          particles::Code::Electron, E0,
           corsika::stack::MomentumVector(rootCS, {0_GeV, 0_GeV, -1_GeV}),
-          geometry::Point(rootCS, {0_m, 0_m, 10_km}), 0_ns});
+          Point(rootCS, {0_m, 0_m, 10_km}), 0_ns});
 
   SECTION("interface") {
 
-    StackInspector<setup::Stack> model(true);
+    StackInspector<TestCascadeStack> model(true);
 
     model.Init();
-    [[maybe_unused]] const process::EProcessReturn ret =
-        model.DoContinuous(particle, track, stack);
-    [[maybe_unused]] const LengthType length = model.MaxStepLength(particle, track);
+    [[maybe_unused]] const process::EProcessReturn ret = model.DoStack(stack);
   }
 }
diff --git a/Processes/TrackingLine/TrackingLine.h b/Processes/TrackingLine/TrackingLine.h
index e847a3fd7ebef23583c632cc5b71af474c883428..a801a2ee2baa206424211151c6a7fb9a616d0b70 100644
--- a/Processes/TrackingLine/TrackingLine.h
+++ b/Processes/TrackingLine/TrackingLine.h
@@ -105,7 +105,8 @@ namespace corsika::process {
               currentLogicalVolumeNode->GetVolume());
           // for the moment we are a bit bold here and assume
           // everything is a sphere, crashes with exception if not
-          auto const [t1, t2] = *TimeOfIntersection(line, sphere);
+          [[maybe_unused]] auto const [t1, t2] = *TimeOfIntersection(line, sphere);
+          [[maybe_unused]] auto dummy_t1 = t1;
           intersections.emplace_back(t2, currentLogicalVolumeNode->GetParent());
         }
 
diff --git a/Processes/TrackingLine/testTrackingLine.cc b/Processes/TrackingLine/testTrackingLine.cc
index fb213f9d8e3729015a8ad2f19c092e3d476bf9dc..1acff46eec0d810138203856b0bb6900e153ce87 100644
--- a/Processes/TrackingLine/testTrackingLine.cc
+++ b/Processes/TrackingLine/testTrackingLine.cc
@@ -91,6 +91,8 @@ TEST_CASE("TrackingLine") {
     Line line(origin, v);
 
     auto const [traj, geomMaxLength, nextVol] = tracking.GetTrack(p);
+    [[maybe_unused]] auto dummy_geomMaxLength = geomMaxLength;
+    [[maybe_unused]] auto dummy_nextVol = nextVol;
 
     REQUIRE((traj.GetPosition(1.) - Point(cs, 0_m, 0_m, radius))
                 .GetComponents(cs)
diff --git a/Setup/SetupStack.h b/Setup/SetupStack.h
index 2dde8fb4fddddf27689c517449bb8ff23f4e94c1..a59ca2aa3815b5a956e17a07faabf61e2834d972 100644
--- a/Setup/SetupStack.h
+++ b/Setup/SetupStack.h
@@ -68,6 +68,8 @@ private:
  *
  * corresponding defintion of a stack-readout object, the iteractor
  * dereference operator will deliver access to these function
+// defintion of a stack-readout object, the iteractor dereference
+// operator will deliver access to these function
  */
 template <typename T, typename TEnvType>
 class GeometryDataInterface : public T {
@@ -146,11 +148,7 @@ namespace corsika::setup {
       corsika::stack::SecondaryView<typename corsika::setup::Stack::StackImpl,
                                     corsika::setup::detail::StackWithGeometryInterface>;
 #elif defined(__GNUC__) || defined(__GNUG__)
-  template <typename S, template <typename> typename _PIType = S::template PIType>
-  struct MakeView {
-    using type = corsika::stack::SecondaryView<typename S::StackImpl, _PIType>;
-  };
-  using StackView = MakeView<corsika::setup::Stack>::type;
+  using StackView = corsika::stack::MakeView<corsika::setup::Stack>::type;
 #endif
 
 } // namespace corsika::setup
diff --git a/Stack/NuclearStackExtension/NuclearStackExtension.h b/Stack/NuclearStackExtension/NuclearStackExtension.h
index 6c1fd2b801120bbe0c22c6c76d22ccadc652f4af..40eb5e0e672883e58cc207324e99d11afdd6be18 100644
--- a/Stack/NuclearStackExtension/NuclearStackExtension.h
+++ b/Stack/NuclearStackExtension/NuclearStackExtension.h
@@ -178,6 +178,8 @@ namespace corsika::stack {
         return InnerParticleInterface<StackIteratorInterface>::GetChargeNumber();
       }
 
+      int GetNucleusRef() const { return GetStackData().GetNucleusRef(GetIndex()); }
+
     protected:
       void SetNucleusRef(const int vR) { GetStackData().SetNucleusRef(GetIndex(), vR); }
     };
diff --git a/Stack/NuclearStackExtension/testNuclearStackExtension.cc b/Stack/NuclearStackExtension/testNuclearStackExtension.cc
index 5185c3538f7b915dd825b8fe1ec98c751903c2a2..c92e5471fdf53e74aa6fdf3e0312e8f0492ae07e 100644
--- a/Stack/NuclearStackExtension/testNuclearStackExtension.cc
+++ b/Stack/NuclearStackExtension/testNuclearStackExtension.cc
@@ -29,10 +29,11 @@ using namespace corsika::units::si;
 // this is an auxiliary help typedef, which I don't know how to put
 // into NuclearStackExtension.h where it belongs...
 template <typename StackIter>
-using ExtendedParticleInterfaceType = stack::nuclear_extension::NuclearParticleInterface<
-    stack::super_stupid::SuperStupidStack::PIType, StackIter>;
+using ExtendedParticleInterfaceType =
+    corsika::stack::nuclear_extension::NuclearParticleInterface<
+        corsika::stack::super_stupid::SuperStupidStack::template PIType, StackIter>;
 
-using ExtStack = NuclearStackExtension<stack::super_stupid::SuperStupidStack,
+using ExtStack = NuclearStackExtension<corsika::stack::super_stupid::SuperStupidStack,
                                        ExtendedParticleInterfaceType>;
 
 #include <iostream>
diff --git a/Stack/SuperStupidStack/SuperStupidStack.h b/Stack/SuperStupidStack/SuperStupidStack.h
index 1610aede7ec0cad53a8e5e92d14ffba5ce1ab973..0b67b95f184bba24358e10980ededdf1dc86c551 100644
--- a/Stack/SuperStupidStack/SuperStupidStack.h
+++ b/Stack/SuperStupidStack/SuperStupidStack.h
@@ -39,6 +39,8 @@ namespace corsika::stack {
     protected:
       using corsika::stack::ParticleBase<StackIteratorInterface>::GetStack;
       using corsika::stack::ParticleBase<StackIteratorInterface>::GetStackData;
+
+    public:
       using corsika::stack::ParticleBase<StackIteratorInterface>::GetIndex;
 
     public: