Ok. After lengthy discussions with Georg this morning, it seems there are quite a number of possible approaches, if I understand things…
Approach 1
Duplicate mark glyph and adjust anchors so the mark sits further to the left. Substitute that version of the glyph before ါ. This is interpolatable and requires no manual GPOS rules, and it can be contextual, but it adds an extra glyph (for each mark that needs contextual positioning, there could be a lot) and needs another lookup in the GSUB rules.
Approach 2
Use only one version of the mark glyph, but add a contextual rule manually to reposition it to the left. This would be interpolatable if using a number token, and can be contextual, but the value of the number token would have to be measured for each master and updated if outlines/sidebearings are adjusted. For scripts with a lot of marks, there will be a lot of number tokens to keep track of, and GPOS rules will need to be written manually to deploy those tokens in the right contexts.
lookup myanmarContextualAboveMarkShift {
lookupflag UseMarkFilteringSet @myanmarAbovemarks;
pos kinzi-myanmar' [aaTall-myanmar aaTall_asat-myanmar] <-120 0 0 0>;
} myanmarContextualAboveMarkShift;
Approach 3
Use a contextual anchor as outlined above. Have a *top anchor on every base (it doesn’t work for *_top anchors on marks yet) and in the anchor context box, input the sequence that should trigger the switch to that anchor. This would be most efficient as there’s no extra glyph or manual GPOS rules to write, but requires the new anchor on every base, and it can’t currently ignore belowmarks or have more than one context rule.

Approach 4
Add a _topleft anchor to the mark, but offset it to the left of the LSB, so it has a negative value. Then tokenise this value in a manual GPOS rule to shift it left from its auto-generated position by that negative amount:
lookup myanmarContextualAboveMarkShift {
lookupflag UseMarkFilteringSet @myanmarAbovemarks;
pos kinzi-myanmar' [aaTall-myanmar aaTall_asat-myanmar] <${kinzi-myanmar:anchors._topleft.x} 0 0 0>;
} myanmarContextualAboveMarkShift;
Approach 5
Define specific anchors manually for this context. This takes the mark out from its usual position and allows it to be positioned absolutely, and can use tokens and be contextual.
# Automatic Code End
markClass kinzi-myanmar <0 0> @TOP_SHIFTLEFT;
lookup myanmarContextualAboveMarkShift {
lookupflag UseMarkFilteringSet @myanmarAbovemarks;
position base @myanmarBaseConsonants' <anchor ${kinzi-myanmar:width} 0> mark @TOP_SHIFTLEFT' [aaTall-myanmar aaTall_asat-myanmar]; # This finds the width of kinzi glyph and places kinzi that amount from the lsb of the base.
} myanmarContextualAboveMarkShift;
This would necessitate either calculations with tokens, or a new rule for each base (they’re all different widths)
I believe Approach 4 does things most efficiently for me in this case
Did I miss some other clever approach?