import bpy,json
from pathlib import Path
P=Path('/opt/creature-lib-20261017/realistic/fox');bpy.ops.wm.read_factory_settings(use_empty=True);bpy.context.scene.render.fps=30;bpy.ops.import_scene.gltf(filepath=str(P/'planted-v5.glb'))
o=next(o for o in bpy.context.scene.objects if o.type=='MESH' and any(m.type=='ARMATURE' for m in o.modifiers));rig=next(o for o in bpy.context.scene.objects if o.type=='ARMATURE');count=0
for v in o.data.vertices:
 p=o.matrix_world@v.co;front=.22 if p.z<.42 else .19
 if p.z<.20:front=.23+(.20-p.z)*.7
 if p.y>front and p.z<.50:
  # Anatomical side-profile boundary, measured on this generated mesh.
  # Rigid whole tail avoids the previous fan stretching between hind leg and tail.
  for g in list(v.groups):o.vertex_groups[g.group].remove([v.index])
  o.vertex_groups['Tail1'].add([v.index],1.,'REPLACE');count+=1
for t in rig.animation_data.nla_tracks:t.mute=True
rig.animation_data.action=bpy.data.actions['Idle'];rig.animation_data.action_slot=rig.animation_data.action.slots[0];bpy.context.scene.frame_set(0);bpy.context.view_layer.update();bpy.ops.object.select_all(action='DESELECT')
for x in bpy.context.scene.objects:
 if x.type in ['ARMATURE','EMPTY'] or x==o:x.select_set(True)
out=P/'tail-v7.glb';assert not out.exists()
bpy.ops.export_scene.gltf(filepath=str(out),export_format='GLB',use_selection=True,export_yup=True,export_animations=True,export_animation_mode='ACTIONS',export_anim_single_armature=True,export_force_sampling=True,export_optimize_animation_size=True,export_influence_nb=4,export_all_influences=False,export_leaf_bone=False,export_image_format='JPEG',export_jpeg_quality=88)
e=json.loads((P/'entry-v5.json').read_text());e['file']='../realistic/fox/tail-v7.glb';(P/'entry-v7.json').write_text(json.dumps(e,indent=2));(P/'tail-repair.json').write_text(json.dumps({'vertices_rigid_tail':count,'method':'Anatomical profile tail isolation, excludes hind paws. Previous feathered corridor stretched the bushy tail during gallop.'},indent=2));print('TAIL',count)
