The single biggest unblock for narrative work: without it the image half is dead on arrival.
Today citizen.physical returns only body_size_cm3, size_modifier, and a three-way build string. mcp_injuriesAndHealth.lua:27 deliberately filters scar_ flags as non-actionable. mcp_military.lua reads u.inventory but only to diff against uniform slots, never to describe what is worn. An image agent handed today's output knows a dwarf's name, mood, and that they are "average build."
Returns
For one unit: physical descriptors (hair/beard/moustache style and length, hair/eye/skin color as descriptors names them), build and size, permanent marks (missing parts, scars), and current kit — worn items by body slot with material, quality, dye, and decorations, plus the wielded weapon.
Phase 1 — investigation (timeboxed, inside this ticket)
Deep version-fragile field walking; probe live on 53.x before committing to the tool shape:
u.appearance.bp_modifiers, .colors, .body_modifiers, .tissue_style — and how each indexes into the caste's appearance_modifiers / color_modifiers in raws.
descriptors.colors / .shapes / .patterns for English rendering (mcp_citizen.lua:218 already reads descriptors.colors for preferences — the pattern exists).
- Permanent marks:
u.body.components.body_part_status[].gone, and the scar_* body-part flags injuries_and_health filters out.
u.inventory item roles beyond the Worn set mcp_military.lua:11 already uses — wielded, quiver, hauled.
Two decisions this phase settles, both recorded in the tool's doc page before implementation:
- Whether DF's own descriptor prose ("her hair is arranged in a bun") is reconstructable, or whether we emit structured modifier facts instead. Dwarf Therapist and Stonesense both do this, so it is proven territory — the question is cost.
- Separate tool vs. expanding
citizen.physical. Leaning separate: citizen is already a large payload and not every call wants a portrait.
Constraints
- Facts-only — emit descriptors as DF names them, no "looks intimidating."
- Fog-of-war:
reqscript('mcp_unitVisibility'), never re-derive the hidden check.
- Sort all lists before emit (golden stability).
The single biggest unblock for narrative work: without it the image half is dead on arrival.
Today
citizen.physicalreturns onlybody_size_cm3,size_modifier, and a three-waybuildstring.mcp_injuriesAndHealth.lua:27deliberately filtersscar_flags as non-actionable.mcp_military.luareadsu.inventorybut only to diff against uniform slots, never to describe what is worn. An image agent handed today's output knows a dwarf's name, mood, and that they are "average build."Returns
For one unit: physical descriptors (hair/beard/moustache style and length, hair/eye/skin color as
descriptorsnames them), build and size, permanent marks (missing parts, scars), and current kit — worn items by body slot with material, quality, dye, and decorations, plus the wielded weapon.Phase 1 — investigation (timeboxed, inside this ticket)
Deep version-fragile field walking; probe live on 53.x before committing to the tool shape:
u.appearance.bp_modifiers,.colors,.body_modifiers,.tissue_style— and how each indexes into the caste'sappearance_modifiers/color_modifiersin raws.descriptors.colors/.shapes/.patternsfor English rendering (mcp_citizen.lua:218already readsdescriptors.colorsfor preferences — the pattern exists).u.body.components.body_part_status[].gone, and thescar_*body-part flagsinjuries_and_healthfilters out.u.inventoryitem roles beyond theWornsetmcp_military.lua:11already uses — wielded, quiver, hauled.Two decisions this phase settles, both recorded in the tool's doc page before implementation:
citizen.physical. Leaning separate:citizenis already a large payload and not every call wants a portrait.Constraints
reqscript('mcp_unitVisibility'), never re-derive the hidden check.