To do that, you have to ensure that the type system of the underlying languge is directly honored/checked by the metaprogram itself. As a practical matter, this almost forces the metaprogramming to be in the underlying language... so I guess I'm not suprised that you might be able to do this in metaocaml.
Most of us don't get metaprogramming tools built into the underlying language (C++ being rather an exception, and I reject it and reflection based systems as being too weak to carry out arbitrary transformations).
A system that can carry out arbitrary transformations (or metaprograms composed of sets of those) on code is the DMS Software Reengineering Toolkit. DMS has front ends for many real langauges, builds compiler data structures when parsing (including ASTs). DMS provides source-to-source program transformations that represent transformations as AST-rewrites using the surface syntax of the target language. It meets your requirement to a certain degree: if your transformation rules are syntactically correct (and they are checked by DMS), then the transformed program will be syntactically correct. It does not achieve your type-correctness requirement, as the type-checking mechanisms are implemented outside the target language. In principal, one could a type-safe checker to augment the program transformations; in practice, we've found that we can code transformations reliably enough.
And even if you have type-safe transformations, you don't have a guarantee of semantic safety with respect to your original program. So, you'll still have to debug the metaprograms.